ITCooky Recetas

Vamos a cocinar it cositas

¡Orange PI PC como un Servedor en Armbian!

дата noviembre 17, 2019

Desenterré un artículo inacabado olvidado, por eso el Armbian es muy viejo, ¡pero en eso hay sus ventajas! Lo rehice y lo reescribí un poco, ¡y aquí está el servidor en Orange Pi Pc! ¿Por qué un servidor? Debido a que es autónomo: tiene un reloj y puede se conectarse a el directamente, hay un apagador seguro, hay un control de temperatura del procesador con un ventilador y hay una pantallar con parámetros como en los servidores de verdad.

Asi de simple subo una image de Armbian.com a Orange Pi Pc para no limitarme hice una Orange Pi especial, por cierto, el diagrama no da tanto miedo como resultó en la foto.

Solía verse así



Pero quité el bread board, corté los cables y los solde a la placa, y se ve más hermoso ahora


Aquí hay un diagrama, la energía pasa por el conector microUSB.

Normalmente descargo la imagen para Orangte PI PC desde aqui https://www.armbian.com/orange-pi-pc/ resulta ser el camino para PC PC PLUS, está bien! Pero en el antiguo kernel 3.4 los ensamblados del servidor no estan, pero tenía Armbian_5.25_Orangepipcplus_Debian_jessie_default_3.4.113

Escribimos en la tarjeta SD: uso una mala Transcend 2 Gb sin especificar la velocidad y el clase. No tengo un app para abrir el archivo en 7z en Ubuntu, así que primero lo instalo:
sudo apt-get install p7zip-full
Ponemos todo en la carpeta deseada y lo descomprimimos
7z e Armbian_5.25_Orangepipcplus_Debian_jessie_default_3.4.113.7z
Formatee la tarjeta SD de cualquier como quiera, yo lo haga a través de Gparted. Y escriba en la tarjeta, tengo la tarjeta en sde1
sudo dd bs=1M if=Armbian_5.25_Orangepipcplus_Debian_jessie_default_3.4.113.img of=/dev/sde

Insertamos la tarjeta en Orange Pi Pc y listo, ¡funciona! Después de cargar, debe ingresar el nombre root y la contraseña 1234, después de eso debe cambiar la contraseña y agregar un usuario, aquí se describe todo http://docs.armbian.com/User-Guide_Getting-Started/ También debe reiniciar un par de veces para usar toda la tarjeta de memoria.

Conéctate a wifi
Sí, no es comun de servidores, pero es necesario para la movilidad. Inserto WiFi USB uno de esos, el enlace ya no funciona, pero el nombre esМини USB адаптер wi-fi RTL 8188EUS Comfast CF-WU810N-1 adaptador беспроводная точка доступа wi-fi USB WiFi ключ adaptador WiFi USB
Este es un viejo Armbian, no hay armbian-config, así que para conectarse a Wi-Fi, ejecute
nmtui-connect
No hay nada que contar, todo está claro.

Aquí se reveló una falla interesante. El Wi-Fi se activo después del reinicio, pero Armbian pensó que todavía estaba en el cable, aunque no había cable y debido a esto, Internet no funcionó. Tuve que hacer
ifdown eth0

Apagado seguro (relativamente, en comparación con arrancar el cable de alimentación, es muy seguro)El problema es que en OrangePi (hasta ahora) no hay ninguna pieza de hardware que apague la alimentación. Pero puede apagar el sistema operativo y luego tirar del cable. Para comprender que el sistema operativo se ha apagado en esta etapa, usaré un Led.
Para comunicarse con GPIO necesita instalar WiringOP

cd /root
git clone https://github.com/zhaolei/WiringOP.git -b h3
cd WiringOP
chmod +x ./build
sudo ./build

Ahora enciende Led, ve a
cd /root/WiringOP/examples/
y hace
vi powerled.c
Añade el code

#include <stdio.h>
#include <wiringPi.h>
#include <unistd.h>
#define LED 2

int main (void)
{
  wiringPiSetup () ;
  pinMode (LED, OUTPUT) ;

for (;;)
  {
usleep(500);
if(digitalRead(LED) == 0)

  {
    digitalWrite (LED, HIGH) ;  // On
    delay (1000) ;
  }
}

  return 0 ;
}

Led esta en el pin 2. El script mira su estado, si está apagado lo enciénde y espera por 1000 milisegundos, bueno, no hace falta hacerlo mil veces al segundo!

PRECAUCIÓN: los ciclos en C cargan el procesador al 100%, por lo que ralentizo usleep () (en milisegundos)

hago make
make ./powerled
y lo copio a root folder
cp ./powerled /root
para iniciar sesión cada vez que arrancamos vamos a cron
crontab -e
Y añade esa linea

@reboot /root/powerled & > /dev/null

Hago update
apt-get update
Instalamos ACPID… no esta instalado jm…
aptitude install acpid

Aquí es donde el plus del antiguo núcleo 3.4 aparece, en el nuevo acpid no funciona en absoluto con el botón de encendido

Luego creamos
vi /etc/acpi/events/button_power
Escribimos aqui

event=button/power
action=/sbin/shutdown -h now

Reinicamos a ACPID
/etc/init.d/acpid restart

Haga clic en el botón power y OrangePi comienza a apagarse, esto se puede ver desde la consola. Cuando se apaga la luz, todos los servicios ya están apagados y el núcleo está en pánico, hay 10 segundos para desconectar el cable de alimentación, si no lo desconecta, comienza a cargarse nuevamente.

Desafortunadamente, no pude hacer que la Led parpadeara después de presionar el botón, solo un comando en acpid, y si pones un enlace al script allí igual no funciona bien …

Más acerca del power
OrangePi tiene un conector de alimentación malisimo, para un modelo aparentemente barato, el conector es desonocido hmm es extraño! Y los cargadores USB van con cable a micro USB claro! Se puede recebir energía atornillando un conector microUSB normal a OrangePi!

Compre unos que se llamaban 10 шт./лот Micro USB к DIP-адаптер 5pin разъем PCB конвертер. Solde cables a GND y VBUS y en OrangePi los conecte a aprimeros 5V y GND. Hasta ahora, todo funciona desde la carga de Samsung en 2A en un cable largo.

Acceso al servidor OrangePi a través del cable USB
Se puede usar un convertidor TTL USB, pero puse el Arduino Nano adentro, así que solo necesito un cable USB. Arduino Nano compre una copia china completa con el chip adecuado para USB, tiene mejor soporte en términos de controladores en todos los sistemas operativos, así se llamaba оригинал Nano 3.0 atmega328 мини-версия FT232RL импортные чипы поддержка win7 Win8 для arduino с usb-кабель.

En Arduino Nano, necesita cortocircuitar GND y RESET y conectarlo a GND y TX, RX de OrangePi.

Como estoy en Ubuntu, entro a la consola de esta manera, instalo
sudo apt install screen
Conectamos Arduino Nano, OrangePi también debe estar encendido!
Miramos donde se quedó la connecion
dmesg | grep tty
normalmemte es ttyUSB0 y connnectamos a el
sudo screen /dev/ttyUSB0 115200
Funciona de manera extraña, al principio no sucede nada, luego, ya sea de presionar una vez o varias el enter, aparece una solicitud de contraseña. En general, una buena manera de conectarse al servidor sin todo en el campo.

Conectamos un reloj DS3231 RTC
Si hay Internet, Armbian establece la hora él mismo, solo necesita elegir su zona horaria
dpkg-reconfigure tzdata

Si no hay Internet, entonces el tiempo comienza desde el último hasta el apagado. Es decir, apagado durante media hora, el tiempo está retrasado media hora.

Instalamos i2c
apt-get install i2c-tools

Miramos donde apareció el reloj
i2cdetect -y 0
esta aqui (un nmumero que no estaba antes)

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 3f 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --   

Ya tengo algo conectado aquí, pero sé que el reloj es 68, debe revivirse ejecutando

sudo echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-0/new_device

Un comando para ver el tiempo
hwclock -r -f /dev/rtc1

Un comando escribir en el reloj el tiempo del systema (hay que hacerlo una vez despues de instalar la bateria al reloj)
hwclock -w -f /dev/rtc1

Para que el reloj se inicie en el arranque y le dé la hora al sistema,
hay que añadir
vi /etc/rc.local
eso antes de la linea exit 0

sudo echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-0/new_device
sudo hwclock -s -f /dev/rtc1

Ventilador de arranque automático cuando se sobrecalienta el CPU
Quería integrar esto en el programa de pantalla, pero no pude obtener un programa de dos bibliotecas diferentes, todo resultó demasiado complicado en el archivo MAKE.

Vamos a
cd /root/WiringOP/examples
Hacemos file
vi coolerstart.c
Añadimos codigo

#include <stdio.h>
#include <wiringPi.h>
#include <unistd.h>
#define LEDR 0
#define COOLER 1
#define WARNING_TEMP 55

int main (void)
{
  int number1;

  wiringPiSetup ();
  pinMode (LEDR, OUTPUT);
  pinMode (COOLER, OUTPUT);
 for (;;)
  {
usleep(1000);
FILE *in_file;


  in_file = fopen("/sys/class/thermal/thermal_zone0/temp", "r");
  if (in_file == NULL)
    {
        printf("Can't open file for reading.\n");
    }
    else
    {
        fscanf(in_file, "%d", &number1);
        fclose(in_file);
    }
 if ( number1 <= WARNING_TEMP)
{

    digitalWrite (COOLER, HIGH);   // Off
    digitalWrite (LEDR, LOW);   // Off

}
else
{
    digitalWrite (LEDR, HIGH);  // On
    digitalWrite (COOLER, LOW);  // On
    delay (150000);               // mS

}

  }
  return 0 ;
}

Esta es la ruta al archivo de temperatura en Armbian /sys/class/thermal/thermal_zone0/temp

compilamos
make coolerstart

Y lo arrancamos en el fondo
./coolerstart & > /dev/null

Para parar un app que funciona al fondo es necesario
pkill coolerstart
Eso para todo que tiene coolerstart*

Empiezo a calentar el CPU con la prueba de sysbench, ya está instalada en Armbian
sysbench --test=cpu --cpu-max-prime=20000 --num-threads=2 run

Funciona, ¡se enfría, no alcanza temperaturas criticas!

file precompilado lo copio al folder root
cp /root/WiringOP/examples/coolerstart /root/
vamos al cron
crontab -e
agregue esta línea (elimine la anterior)
@reboot /root/coolerstart & > /dev/null

y ya funciona

Conectando la pantalla lcm1602

Descargue esta biblioteca. Es simple, en parte de: no se puede borrar una línea solo todo una pantalla, no se puede insertar a un lugar exacto solo desde el principio de una línea.
git clone https://github.com/wargio/liblcm1602.git
cd liblcm1602
make

La pantalla esta en el adress 3f se podria ver eso en el resultado del comando i2cdetect -y 0
Redactamos
vi test.c
aqui hay que cambier value 0x37 a 0x3f

i2c_dev = open_i2c(I2C_FILE_NAME, 0x3f);

Lo compilamos y lo arrancamos
make test
./test

Funciona

Vamos adelante
Para compilar un file con nuestro nombre, agregue el nombre de server_monitoring aquí
vi Makefile
editamos esa lina para que este asi

EXAMPLES=       server_monitoring test example example2 example3

Compilamos file
vi server_monitoring
Aqui esta todo el code

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "i2c.h"
#include "lcd.h"
#include <time.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <unistd.h>
#define I2C_FILE_NAME "/dev/i2c-0"
#define TIME_TO_WAIT 2 

int main(){
int text=0;
int number1;
int number2;
clock_t last = clock();  
char txt[100];
   
// for Ip start     
 char ip_address_wlan[100];
 char ip_address_eth[100];
//for ip end


//for lcd start
 int i2c_dev;
    lcd lcd0;
    // 0x27 the address of the i2c device
    i2c_dev = open_i2c(I2C_FILE_NAME, 0x3f);
    if(i2c_dev <0){
       printf("Errore: %d\n", i2c_dev);
       return 1;
    }
lcd_init(&lcd0, i2c_dev);
    char vremya[100];
lcd_clear(&lcd0);
//for lcd end

for (;;)
  {


usleep(100);


clock_t current = clock();

//time loop start
    time_t now = time (0);
       strftime (vremya, 100, "%d%mY%y %H:%M:%S", localtime (&now));
lcd_print(&lcd0, vremya, 16,0);
//time loop end

if (current >= (last + TIME_TO_WAIT * CLOCKS_PER_SEC) && text == 0) {
int fd;
    struct ifreq ifr;    
fd = socket(AF_INET, SOCK_DGRAM, 0);
    ifr.ifr_addr.sa_family = AF_INET;
    memcpy(ifr.ifr_name, "wlan0", IFNAMSIZ-1);
    ioctl(fd, SIOCGIFADDR, &ifr);
    close(fd);
    strcpy(ip_address_wlan,inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
sprintf(txt, "w%s", ip_address_wlan);
lcd_print(&lcd0,"                ", 16,1);
lcd_print(&lcd0,txt, strlen(txt),1);

last = current;
text = 1;
}     

else if (current >= (last + TIME_TO_WAIT * CLOCKS_PER_SEC) && text == 1) {
int fd;
    struct ifreq ifr;    
fd = socket(AF_INET, SOCK_DGRAM, 0);
    ifr.ifr_addr.sa_family = AF_INET;
    memcpy(ifr.ifr_name, "eth0", IFNAMSIZ-1);
    ioctl(fd, SIOCGIFADDR, &ifr);
    close(fd);
   strcpy(ip_address_eth, inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
sprintf(txt, "e%s", ip_address_eth);
lcd_print(&lcd0,"                ", 16,1);
lcd_print(&lcd0,txt, strlen(txt),1);
last = current;
text = 2;
}
else if (current >= (last + TIME_TO_WAIT * CLOCKS_PER_SEC) && text == 2) {

FILE *in_file;
  in_file = fopen("/sys/class/thermal/thermal_zone0/temp", "r");
if (in_file == NULL)
    {
        printf("Can't open file for reading.\n");
    }
    else
    {
        fscanf(in_file, "%d", &number1);
        fclose(in_file);
    }

char cmd[]="df -BM /  | tail -1 | awk '{print $4}'" ;
FILE* apipe = popen(cmd, "r");
 
if (apipe == NULL)
    {
        printf("Can't open file for reading.\n");
    }
    else
    {
        fscanf(apipe, "%d", &number2);
pclose(apipe);
    
}





sprintf(txt, "CPU:%dC S:%dMb", number1,number2);
lcd_print(&lcd0,"                ", 16,1);
lcd_print(&lcd0,txt, strlen(txt),1);
last = current;
text = 0;
}


}
close_i2c(i2c_dev);

return 0;
}

compilamos
make server_monitoring
Copié el archivo compilado en el directorio root
cp /root/liblcm1602/server_monitoring /root/
vamos al cron
crontab -e
Añadimos esa linea (borramos la anterior)
@reboot /root/server_monitoringt & > /dev/null
rebootamos

Como siempre, me ayudo a programar Google. Cómo en C tomar un IP lo copie desde aquíhttps://www.includehelp.com/c-programs/get-ip-address-in-linux.aspx no entendí cómo funciona y cómo configurarlo por mís nesecidades… funciona así que si todas las interfaces no están conectadas, mostrará algo generico, si un interfaz está conectada muestra su ip, si dos están conectados, ambos se muestran, si uno se desconecta, igual muestra lo que habia antes … ¡me vale!
Para una línea con temperatura y espacio libre, también quería usar C para calcular el espacio libre, pero resultó ser demasiado difícil, pero puede poner los comandos habituales de la consola en C – y lo hice.

El programa consume el 60% de la CPU, aparentemente este es un pago por el tiempo en segundos para actualizar la pantalla 10 veces por segundo. Luego mejorare ese consumo!

Backup y reemplazo de disco
Cambie la tarjeta SD «mala» por una «buena» SanDisk Ultra 16gb clase 10
antes de eso mido la velocidad de la mala
mkdir /root/test
cd /root/test
sysbench --test=fileio --file-total-size=100Mb prepare
sysbench --test=fileio --file-total-size=100Mb --file-test-mode=rndrw --init-rng=on --max-time=300 --max-requests=0 run > test.io

resultado 186.63Kb/sec

Sacamos la tarjeta SD y la insertamos en la computadora en Ubuntu
Miro donde apareció ella, en mi pc sde
y hago el backup
sudo dd if=/dev/sde of=./armbian_server_itcooky.img bs=1M

Al final sacamos la mala, insertamos la buena tarjeta y hacemos
sudo umount /dev/sde1
sudo mkfs.vfat -I /dev/sde
sudo dd if=./armbian_server_itcooky.img of=/dev/sde bs=1M

Uhhh, Armbian tiene algún tipo de problema con cambiar el tamaño de las tarjetas ahora, así que con el tamaño de la image hago el mismo test.
Y el resultado es 1.202Mb/sec

UPD: Reescribimos el controlador del ventilador y la pantalla de información en Node.js
Aparentemente, todos los programas en C, consumen el 80% de la CPU. Noté que el monstruo Node-Red no come nada en absoluto, pero ¿qué pasa si escribo todo en Node.js. Dire de ante mano, que si, lo hice y el consume de CPU se redujo en mas de 4 veces.

Primero instalamos nodejs
vamos aca
cd /root
ademas
curl -sL https://deb.nodesource.com/setup_9.x | bash -
apt-get install -y nodejs

Ponemos un módulo que le permitirá ejecutar comandos de consola ennode.js
npm i node-cmd
También es necesario compilar un programa para la pantalla para enviar texto a la pantalla desde la consola. liblcm1602 actualiza la informacion borrando toda la pantalla, esto lleva a parpadear. Así que tome otro biblioteca que puede actualizar línea por línea, y tmbn apagar la pantalla por completo. Pero coloca el cursor al final; lo eliminaré agregando espacios adicionales a la línea (estúpidamente). También es importante actualizar la pantalla desde un lugar en el programa, y debido a la asincronía (así lo decidí), si ejecutan el comando de actualización desde diferentes lugares del programa, se eliminan mutuamente.

cd /root
git clone https://github.com/bitbank2/LCD1602.git
cd LCD1602
make
cp main.c mainOLD.c

Añado al main.c
vi main.c
eso

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <lcd1602.h>

int main(int argc, char **argv)
{
int rc;
        rc = lcd1602Init(0, 0x3f);
        if (rc)
        {
                printf("Initialization failed; aborting...\n");
                return 0;
        }
int s = *(argv[2]) -'0' -1;

lcd1602SetCursor(0,s);
        lcd1602WriteString(argv[1]);
//      lcd1602Control(1,0,1); // backlight on, underline off, blink block on
//      getchar();
//      lcd1602Shutdown();
return 0;
} /* main() */

Para mi pantalla cambie rc = lcd1602Init(0, 0x3f);
– 0 se debe a que pantalla esta en 0 de i2c
– 0x3f es su adress

compilamos
make -f make_demo
y lo copiamos al root
cp ./demo /root/demo

Creamos
vi /root/server_monitoring.js
Añadimos

var cmd=require('node-cmd');
var sec = 61;
var min = 0;
var hour = 0;
var day = 0;
var month =0;
var year = 0;
text2 = "Booting...      ";
textn = 1;
cputemp = 0;
cputempwar = 45;
cputemptime = 60;  //in 0,5 sec
cputimer = 0;

function coolercpu () {
cmd.get(
        '/bin/cat /sys/class/thermal/thermal_zone0/temp',
        function(err, data, stderr)
{ cputemp = data.replace(/[^0-9]+/, '');

if (cputemp > cputempwar) {
cmd.get(
        'gpio read 1',
        function(err, data, stderr){
  if (data == 1) {
textn = 4;
cmd.get(
`
         gpio mode 0 out
         gpio write 0 on
         gpio mode 1 out
         gpio write 1 off
`,
        function(err, data, stderr){
 cputimer= cputemptime;

});
}
;});

} else {
 cmd.get(
        'gpio read 1',
        function(err, data, stderr){
if (data == 0 && cputimer > 0) {
cputimer = cputimer - 1;
};

  if (data == 0 && cputimer <= 0) {
 cmd.get(
`
         gpio write 0 off
         gpio write 1 on 
`,
        function(err, data, stderr){
textn = 5; 
});
};});
};
});
};
setInterval(coolercpu, 500);


function ledon(){ 
    cmd.get(
        'gpio read 2',
        function(err, data, stderr){
  if (data == 0) {
            
cmd.get(
        `gpio mode 2 out
         gpio write 2 on`,
        function(err, data, stderr){
});};
});
};
setInterval(ledon, 1000);

//start screen
function screen(){
var date = new Date();
  if ( date.getSeconds() != sec ) {
sec = date.getSeconds();
sec = (date.getSeconds() <  10 ? "0" : "") + date.getSeconds();
hour = (date.getHours() < 10 ? "0" : "") + date.getHours();
min = (date.getMinutes() < 10 ? "0" : "") + date.getMinutes();
year = date.getFullYear().toString().substr(-2); 
year = (year < 10 ? "0" : "") + year;    
month = date.getMonth() + 1;
month = (month < 10 ? "0" : "") + month;
day = (date.getDate() < 10 ? "0" : "") + date.getDate();


//cmd.run('/root/example2 "' + day + month + 'Y' + year + ' ' + hour + ':' + min + ':' + sec + '" "' + text2 + '"');
cmd.run('/root/demo "' + day + month + 'Y' + year + ' ' + hour + ':' + min + ':' + sec + '" 1&&/root/demo "'+ text2 + '" 2');

};
};
setInterval(screen, 10);

function textforscreen(){
switch (textn) {
case 1:
textn = 2;
cmd.get(
'/sbin/ip addr list wlan0 |/bin/grep "inet " |/usr/bin/cut -d\' \' -f6|/usr/bin/cut -d/ -f1',
        function(err, data, stderr){
data = data.substring(0, data.length - 1); 
if(data !== null && data !== '') {
text2 = "w" + data + "          ";
} else {
textforscreen();
};
});
break;
case 2:
textn = 3;
cmd.get(
'/sbin/ip addr list eth0 |/bin/grep "inet " |/usr/bin/cut -d\' \' -f6|/usr/bin/cut -d/ -f1',
        function(err, data, stderr){
data = data.substring(0, data.length - 1);
if(data !== null && data !== '') {
text2 = "e" + data + "          ";
} else {
textforscreen();
};
});
break;
case 3:
cmd.get(
'/bin/df -BM /  | /usr/bin/tail -1 | /usr/bin/awk \'{print $4}\'',
        function(err, data, stderr){
data = data.substring(0, data.length - 1);
text2 = "CPU:" + cputemp + "C S:" + data + "     ";
textn = 1;
});
break;
case 4:
text2 = "Cooler on  " + cputemp + "C       ";
textn = 3;
break;
case 5:
text2 = "Cooler off " + cputemp + "C       ";
textn = 3;
break;
}
};

setInterval(textforscreen, 3000);

Para que se arranca en el boot hay que instalar pm2
npm i pm2 -g
arrancalo
pm2 start server_monitoring.js --name Server-mon
y eso lo hace arrnar en el boot
pm2 startup
pm2 save

Hacemos reboot

Y funciona, a partir de las ventajas, la carga del procesador disminuyó, lo mao es que habia un parpadeo de la pantalla pero ya lo corregi!

¿Qué hace el programa y las funciones?
coolercpu – toma la temperatura del procesador con un comando de consola, lo asigna a una variable (se necesitará más adelante). Si la temperatura es superior a 45, entonces si el pin del ventilador está apagado (está invertido debido al transistor, se determina como encendido), se enciende, y la variable que determina qué texto mostrar en la pantalla da un valor de 5: allí se enciende el texto con: status del ventilador y el valor de temperatura. Y también la cifra de temperatura se limpia de basura, que se pega cuando lo tomas de un archivo, a JS no le importa (C me haria un quilombo por eso) igual funciona así, pero cuando se muestra en la pantalla, aparece un artefacto al final, por lo tanto, todos los no dígitos se eliminan de cputemp variable.

ledon – eso se dice por simismo

screen – se trata de la pantalla, la pantalla se actualiza una vez por segundo, toma el tiempo, si los segundos han cambiado, se actualiza. Muestra la fecha y uno de los 5 textos. El tiempo se verifica si los números son menores a 10 antes de agregar el cero en frente.

textforscreen – estos son los textos que se cambian cada 3 segundos. 1 y 2 toman un IP, algo de basura también se pone al final, por lo que se elimina el último symbolo. Si no hay IP, entonces el siguiente valor está determinado por la variable y la función se inicia por sí misma … al igual al comando GO TO de BASIC que extraño muchichicimo en los lenguages modernos. Debido a eso, todos los textos permanecen en la pantalla durante 3 segundos, de no ser por la IP vacía, el texto anterior se quedaría más tiempo.

Agregamos botones a Orange Pi Pc en Node.Js y WiringOP
Parece simple, y es simple, pero no. Arduino (en el microcontrolador, en el FPGA aún más) se las arreglaría con los ojos cerrados, y para cualquier CPU es una tarea imposible. El procesador OrangePi actualizando el estado de pins cada 10milisegundos consume 100% de su potencia, por leso lo voy hacer cada 150mils … Sin embargo, el CPU no intenta repartir la carga con los 4 núcleos, Node.js tampoco puede ejecutar aplicaciones en un núcleo específico, solo en pm2 modo de clúster, pero ejecuta la misma aplicación en todos los núcleos, útil solo para la web.

El botón está en el pin 5 y 6, los botones tiene la parte superior e inferior – cuidado con eso!

Hay un módulo para trabajar con GPIO para Node.js https://www.npmjs.com/package/orange-pi-gpio pero si lo miras, él hace lo mismo, envía comandos de consola a WiringOP, puedes hacerlo sin él.

Aquí hay un programa solo para revisar botones y sus dedos

const exec = require('child_process').exec;
n1 = 0;
p1 = 0;
n2 = 0;
p2 = 0;
once = 0;

if (once == 0)
{
cmd('gpio mode 5 in&&gpio mode 5 up');
cmd('gpio mode 6 in&&gpio mode 6 up');
console.log('Pins Ready');
once = 1;
};

function cmd(command) {
        return new Promise((resolve, reject)=> {
            exec(command, (error, stdout, stderr) => {
                if (error) {
                    reject(error);
                }
                resolve(stdout);
            });
});};


function button () {
cmd('gpio read 5')
.then((state)=>{
if (state == 0) {
n1 = n1 + 1;
console.log('5 count: %d', n1);
}
else { 
if (n1 > 0 ) {
p1 = p1 + 1;
if (p1 >= 3 ) {
n1 = 0;
p1 = 0;
console.log('5 none: %d', n1);
};};};});
cmd(`gpio read 6`)
.then((state)=>{
if (state == 0) {
n2 = n2 + 1;
console.log('6 count: %d', n2);
}
else {
if (n2 > 0 ) {
p2 = p2 + 1;
if (p2 >= 3 ) {
n2 = 0;
p2 = 0;
console.log('6 none: %d', n2);
};};};});
setTimeout(button, 150);
};
setTimeout(button, 10);

creamos un file
vi button.js
y lo arrancamos
node ./button.js

Los dedos, de cada uno, son casi iguales y aquí puede ver cómo funcionan con botones en condiciones reales. Puede aumentar la frecuencia de los botones de sondeo en una fila, reduciendo el número
setTimeout(button, 150);
Es mejor usar setTimeout, en lugar de setInterval, para que cada ciclo de espera de los botones comience después del final del anterior. Cuando captura un boton presionado, imprime uno, a lo contrario, imprime cero y ambos deben estar claros, dependiendo de la velocidad de la encuesta.

Cmd solo crea un proceso y pone un comando de consola allí. El resultado de ejecutar esta función no es una respuesta o un número, sino un estado: el estado «Prometo responderte» (Promesa), por lo tanto, para reclamar la respuesta, la siguiente línea es then. No entendía bien cómo funciona, pero todo es asíncrono, pero muy sincrónico: si cada una de esas funciones tubiera su propio identificador y se podría esperar una respuesta segun el entonces si … de lo contrario, todo parece ser sincrónico, pero es asincrónico.

Para la pantalla, reescribo la salida de pantalla nuevamente
pongo en в main.c

cd /root/LCD1602
vi main.c

eso

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <lcd1602.h>

int main(int argc, char **argv)
{
int rc;
        rc = lcd1602Init(0, 0x3f);
        if (rc)
        {
                printf("Initialization failed; aborting...\n");
                return 0;
        }
int b = *(argv[3]) -'0';
if (b != 0) {
lcd1602SetCursor(0,0);
        lcd1602WriteString(argv[1]);
lcd1602SetCursor(0,1);
        lcd1602WriteString(argv[2]);
} else {
lcd1602Shutdown();
};
return 0;
} /* main() */

compilamos
make -f make_demo
y lo copio a root
cp ./demo /root/demo

Y aquí está el nuevo código con botones. Presionando el botón izquierdo apago la pantalla. Al presionar el botón derecho se apaga / enciende la rotación de la línea con informacion. Cuando se enciende el ventilador, la pantalla se apaga, parece que carecen de suficiente electricidad juntos, a veces incluso se congela. Se agregó una línea de información más. El procesador se carga en un 35% -50% lo minimo que pude…

var sec = 61;
var min = 0;
var hour = 0;
var day = 0;
var month =0;
var year = 0;
text2 = "Booting...      ";
textn = 1;
cputemp = 0;
cputempwar = 45;
cputemptime = 60;  //in 0,5 sec
cputimer = 0;
backlight = 1;
screenloop = 1;
screentimer = 5;
t = 0;
n1 = 0;
p1 = 0;
n2 = 0;
p2 = 0;
const exec = require('child_process').exec;
once = 0;


function cmd(command) {
        return new Promise((resolve, reject)=> {
            exec(command, (error, stdout, stderr) => {
                if (error) {
                    reject(error);
                }
                resolve(stdout);
            });
});};


if (once == 0)
{
cmd('gpio mode 5 in&&gpio mode 5 up');
cmd('gpio mode 6 in&&gpio mode 6 up');
cmd('gpio mode 0 out&&gpio mode 1 out&&gpio mode 2 out');
once = 1;
};


function button () {

cmd('gpio read 5')
.then((state)=>{
if (state == 0) {
n1 = n1 + 1;
}
else {
if (n1 > 0 ) {
p1 = p1 + 1;
if (p1 >= 3 ) {
if (n1 >= 1&& n1 <= 10){
if (screenloop == 1)
{
screenloop = 0;
t = 0;
}
else
{
screenloop = 1;
t = screentimer;
};
};

n1 = 0;
p1 = 0;
};};};});

cmd('gpio read 6')Ощеф
.then((state)=>{
if (state == 0) {
n2 = n2 + 1;
}
else {
if (n2 > 0 ) {
p2 = p2 + 1;
if (p2 >= 3 ) {

if (n2 >= 1&& n2 <= 10){
if (backlight == 1)
{backlight = 0;}
else
{backlight = 1;};

};

n2 = 0;
p2 = 0;
};};};});

setTimeout(button, 150);

};
setTimeout(button, 1000);





function coolercpu () {
cmd ('/bin/cat /sys/class/thermal/thermal_zone0/temp')
     .then((state)=>{ 
cputemp = state.replace(/[^0-9]+/, '');

if (cputemp > cputempwar) {
cmd ('gpio read 1')
    .then((state)=>{ 
  if (state == 1) {
textn = 100;
cmd('gpio write 0 on&&gpio write 1 off');
cputimer= cputemptime;
backlight = 0;

};
});

} else {
cmd ('gpio read 1')
.then((state)=>{
if (state == 0 && cputimer > 0) {
cputimer = cputimer - 1;
};

  if (state == 0 && cputimer <= 0) {
cmd('gpio write 0 off&&gpio write 1 on');        
backlight = 1;
textn = 101; 
};});};

});
setTimeout(coolercpu, 500);
};

setTimeout(coolercpu, 500);


function ledon(){ 
  
cmd('gpio read 2')
.then((state)=>{

if (state == 0) {
cmd('gpio write 2 on');            

};});};
setInterval(ledon, 1300);

//start screen
function screen(){

if (backlight !=3) {
var date = new Date();
  if ( date.getSeconds() != sec ) {
sec = date.getSeconds();
sec = (date.getSeconds() <  10 ? "0" : "") + date.getSeconds();
hour = (date.getHours() < 10 ? "0" : "") + date.getHours();
min = (date.getMinutes() < 10 ? "0" : "") + date.getMinutes();
year = date.getFullYear().toString().substr(-2); 
year = (year < 10 ? "0" : "") + year;    
month = date.getMonth() + 1;
month = (month < 10 ? "0" : "") + month;
day = (date.getDate() < 10 ? "0" : "") + date.getDate();


//cmd.run('/root/example2 "' + day + month + 'Y' + year + ' ' + hour + ':' + min + ':' + sec + '" "' + text2 + '"');
cmd('/root/demo "' + day + month + 'Y' + year + ' ' + hour + ':' + min + ':' + sec + '" "'+ text2 + '" ' + backlight);
if (backlight == 0) { 
backlight = 3;
};

};
};
setTimeout(screen, 30);
};
setTimeout(screen, 50);

function textforscreen(){
switch (textn) {
case 1:
cmd('/sbin/ip addr list wlan0 |/bin/grep "inet " |/usr/bin/cut -d\' \' -f6|/usr/bin/cut -d/ -f1')
.then((state)=>{
status = state.substring(0, state.length - 1);
//status = state;
if(status !== null && status !== '') {
text2 = "w" + status + "          ";
if (screenloop == 1){
if (t >= screentimer)
{textn = 2;
t = 0;
} else {
t = t + 1;
};
};
} else {
textn = 2;
textforscreen();
};
});
break;
case 2:
cmd('/sbin/ip addr list eth0 |/bin/grep "inet " |/usr/bin/cut -d\' \' -f6|/usr/bin/cut -d/ -f1')
.then((state)=>{
status = state.substring(0, state.length - 1);
if(status !== null && status !== '') {
text2 = "e" + status + "          ";
if (screenloop == 1){
if (t >= screentimer)
{textn = 3;
t = 0;
} else {
t = t + 1;
};
};

} else {
textn = 3;
textforscreen();
};
});
break;
case 3:
cmd('/bin/df -BM /  | /usr/bin/tail -1 | /usr/bin/awk \'{print $4}\'')
.then((state)=>{
//status = state.substring(0, state.length - 1);
status = state;
text2 = "CPU:" + cputemp + "C S:" + status + "Mb     ";
});
if (screenloop == 1){
if (t >= screentimer)
{textn = 4;
t = 0;
} else {
t = t + 1;
};
};
break;

case 4:
cmd('/bin/cat /proc/loadavg | /usr/bin/awk \'{print $1,$2,$3}\'')
.then((state)=>{
//status = state.substring(0, state.length - 1);
status = state;
text2 = "L:" + status + "     ";
if (screenloop == 1){
if (t >= screentimer)
{textn = 1;
t = 0; 
} else {
t = t + 1;
};
};


});
break;
case 100:
text2 = "Cooler on  " + cputemp + "C       ";
textn = 3;
break;
case 101:
text2 = "Cooler off " + cputemp + "C       ";

textn = 3;

break;
}
};

setInterval(textforscreen, 750);


Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *