Indice dei contenuti
ToggleQuesta guida aiuta gli sviluppatori a familiarizzare rapidamente con l'EC700, trattando argomenti quali la comunicazione tramite porta seriale, il controllo degli I/O digitali, l'integrazione delle API REST, la gestione del software preinstallato e la personalizzazione del logo di avvio.
L'EC700 è un PC industriale per l'edge computing basato sull'intelligenza artificiale, alimentato dal processore Rockchip RK3588J con NPU integrata da 6 TOPS, progettato per l'inferenza AI direttamente sul dispositivo. Viene comunemente impiegato nella produzione intelligente, nell'ispezione visiva industriale e in altri scenari di intelligenza artificiale. Consulta la scheda tecnica completa su Pagina del prodotto EC700.
Prerequisiti e strumenti per lo sviluppo di EC700
La presente guida si riferisce al gateway EC700. Prima di iniziare, assicurati di avere a disposizione i seguenti strumenti. Scarica i seguenti strumenti dal sito pagina di download.
Client SSH
Si consiglia di utilizzare MobaXterm, oppure è possibile utilizzare qualsiasi client SSH con cui si ha familiarità.
Strumento di debug seriale
Si consiglia di utilizzare XCOM, oppure è possibile utilizzare qualsiasi terminale seriale si preferisca.
Accessori hardware
Tra gli strumenti ausiliari più comuni per il debug figurano gli adattatori da USB a RS485, i cavi Ethernet, ecc. Ti preghiamo di prepararli tu stesso.
Toolchain per la compilazione incrociata
Se si stanno compilando applicazioni native in C/C++ su un PC host e si sta effettuando la distribuzione sull'EC700.
Ambiente software
L'EC700 viene fornito con un ambiente Linux completamente integrato. Ecco cosa c'è sotto il cofano:
| Software | Versione |
|---|---|
| OS | Linux integrato |
| Kernel | Linux 6.1.118 |
| Node.js | v22.17.0 |
| Python | Python 3.10.12 |
| Conchiglia | bash |
| Docker | V27.4.1 |
| Qt | V5.15.3 |
| Ambiente desktop | Xfce4 |
Risorse del dispositivo
| Categoria | Dettagli | Osservazioni |
|---|---|---|
| Immagazzinamento | 128 GB in totale | ~108 GB di spazio libero di serie; espandibile tramite scheda SD o SSD M.2 NVMe |
| Memoria | 8 GB | ~6 GB di spazio libero già pronto all'uso |
| CPU | RK3588 | ~98% inattivo appena tolto dalla confezione |
| NPU | 6 TOP | ~100% inattivo appena tolto dalla confezione |
Interfacce periferiche
1. Porta di debug
L'EC700 rende accessibile la porta seriale di debug del sistema tramite un Tipo-C interfaccia. Utilizza queste impostazioni nel tuo terminale seriale:
- Velocità di trasmissione: 115200
- Bit di dati: 8
- Bit di stop: 1
- Parità: Nessuna
- Controllo del flusso: Nessuno
- Nome utente predefinito: root
- Password predefinita: Consulta la documentazione sui permessi dei sistemi aperti.
2. Porte seriali (RS485 / RS232)
L'EC700 dispone di due canali RS485 e un canale RS232:
| Interfaccia hardware | File del dispositivo |
|---|---|
| RS485-1 | /dev/ttyS3 (corrisponde a A1 / B1) |
| RS485-2 | /dev/ttyS4 (corrisponde a A2 / B2) |
| RS232 | /dev/ttyS1 (corrisponde a TXD / RTD) |
Nota: Le porte RS485 utilizzano il controllo automatico della direzione. Non è necessario passare manualmente dalla modalità di trasmissione a quella di ricezione: l'hardware lo gestisce automaticamente.
2.1 Test rapido
Utilizza il minicom strumento di prova. Per ulteriori dettagli sull'utilizzo, consultare le risorse online o cercare su GPT/Google.
2.2 Esempio di codice in C
#include
#include
#include
#include
#include
#include
#include
#include
#define BUFFER_SIZE 256
typedef struct {
int baud_rate; // Velocità di trasmissione
int data_bits; // Bit di dati (5, 6, 7, 8)
int stop_bits; // Bit di stop (1,2)
char parity; // Bit di parità (N: Nessuna, O: Dispari, E: Pari)
} SerialConfig;
int set_serial_attr(int fd, SerialConfig *config)
{
struct termios tty;
if (tcgetattr(fd, &tty) baud_rate) {
case 9600: speed = B9600; break;
case 19200: speed = B19200; break;
case 38400: speed = B38400; break;
case 57600: speed = B57600; break;
case 115200: speed = B115200; break;
default:
fprintf(stderr, "Velocità di trasmissione non supportata, si utilizza 115200\n");
velocità = B115200;
}
cfsetispeed(&tty, velocità);
cfsetospeed(&tty, velocità);
// Imposta i bit di dati
tty.c_cflag &= ~CSIZE;
switch (config->data_bits) {
case 5: tty.c_cflag |= CS5; break;
case 6: tty.c_cflag |= CS6; break;
case 7: tty.c_cflag |= CS7; break;
case 8: tty.c_cflag |= CS8; break;
default:
fprintf(stderr, "Bit di dati non supportati, si utilizzano 8\n");
tty.c_cflag |= CS8;
}
// Imposta i bit di stop
if (config->stop_bits == 2) {
tty.c_cflag |= CSTOPB;
} else {
tty.c_cflag &= ~CSTOPB;
}
// Imposta il bit di parità
switch (config->parity) {
case 'N': case 'n':
tty.c_cflag &= ~PARENB; // Nessuna
break;
case 'O': case 'o':
tty.c_cflag |= PARENB; // Dispari
tty.c_cflag |= PARODD;
break;
case 'E': case 'e':
tty.c_cflag |= PARENB; // Pari
tty.c_cflag &= ~PARODD;
break;
default:
fprintf(stderr, "Parità non supportata, si utilizza N\n");
tty.c_cflag &= ~PARENB;
}
// Altre impostazioni
tty.c_cflag |= (CLOCAL | CREAD); // Abilita la modalità ricevitore e locale
tty.c_cflag &= ~CRTSCTS; // Disabilita il controllo di flusso hardware
tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // Modalità di input grezza
tty.c_oflag &= ~OPOST; // Modalità di output grezza
tty.c_cc[VMIN] = 1; // Numero minimo di caratteri da leggere
tty.c_cc[VTIME] = 0; // Timeout di lettura (unità: 0,1 secondi)
if (tcsetattr(fd, TCSANOW, &tty) < 0) {
perror("tcsetattr");
return -1;
}
return 0;
}
int main(int argc, char *argv[])
{
int fd;
char *portname;
if (argc < 2) {
fprintf(stderr, "Uso: %s \n", argv[0]);
exit(EXIT_FAILURE);
}
portname = argv[1];
// Configura i parametri della porta seriale
SerialConfig config = {
.baud_rate = 115200, // Velocità di trasmissione
.data_bits = 8, // Bit di dati
.stop_bits = 1, // Bit di stop
.parity = 'N' // Parità (N: Nessuna, O: Dispari, E: Pari)
};
fd = open(portname, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (fd < 0) {
perror("open");
exit(EXIT_FAILURE);
}
if (set_serial_attr(fd, &config)) {
close(fd);
exit(EXIT_FAILURE);
}
printf("Test di eco della porta seriale in esecuzione su %s\n", portname);
printf("Configurazione: baud %d, bit di dati %d, bit di stop %d, parità %c\n",
config.baud_rate, config.data_bits, config.stop_bits, config.parity);
printf("Premere Ctrl+C per uscire.\n");
fd_set readfds;
char buffer[BUFFER_SIZE];
int n;
while (1) {
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
// Attesa indefinita per l'arrivo dei dati (impostazione del timeout rimossa)
if (select(fd + 1, &readfds, NULL, NULL, NULL) 0) {
buffer[n] = '\0';
printf("Byte ricevuti: %d\n", n, buffer);
// Ripetizione dei dati
write(fd, buffer, n);
} else if (n < 0) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
perror("read");
break;
}
}
}
}
close(fd);
return 0;
}
Compilazione: gcc rs485_example.c -o rs485_example
Test RS485-1: ./rs485_example /dev/ttyS3
2.3 Esempio di codice Python
import serial
import select
import sys
import tty
class SerialConfig:
def __init__(self):
self.baud_rate = 115200 # Velocità di trasmissione
self.data_bits = 8 # Bit di dati
self.stop_bits = 1 # Bit di stop
self.parity = 'N' # Parità (N: Nessuna, O: Dispari, E: Pari)
def set_serial_config(ser, config):
"""Configura i parametri della porta seriale"""
# Imposta la velocità di trasmissione
ser.baudrate = config.baud_rate
# Imposta i bit di dati
if config.data_bits == 5:
ser.bytesize = serial.FIVEBITS
elif config.data_bits == 6:
ser.bytesize = serial.SIXBITS
elif config.data_bits == 7:
ser.bytesize = serial.SEVENBITS
else: # Impostazione predefinita a 8 bit
ser.bytesize = serial.EIGHTBITS
# Imposta i bit di stop
if config.stop_bits == 2:
ser.stopbits = serial.STOPBITS_TWO
else: # Impostazione predefinita: 1 bit
ser.stopbits = serial.STOPBITS_ONE
# Imposta la parità
if config.parity.upper() == 'O':
ser.parity = serial.PARITY_ODD
elif config.parity.upper() == 'E':
ser.parity = serial.PARITY_EVEN
altrimenti: # Impostazione predefinita: nessuna
ser.parity = serial.PARITY_NONE
# Disabilita il controllo di flusso hardware
ser.rtscts = False
# Disabilita il controllo di flusso software
ser.xonxoff = False
# Imposta il timeout
ser.timeout = 0.1 # Timeout di 100 ms
return ser
def main():
if len(sys.argv) < 2:
print(f"Uso: {sys.argv[0]} ")
print(f"Esempio: {sys.argv[0]} /dev/ttyS7")
sys.exit(1)
portname = sys.argv[1]
buff_size = 256
# Inizializza la configurazione seriale
config = SerialConfig()
try:
# Apri la porta seriale
ser = serial.Serial()
ser.port = portname
# Applica la configurazione e apri la porta seriale
ser = set_serial_config(ser, config)
ser.open()
if not ser.is_open:
print("Impossibile aprire la porta seriale")
sys.exit(1)
print(f"Porta seriale {portname} aperta con successo")
print(f"Configurazione: Velocità di trasmissione {config.baud_rate}, Bit di dati {config.data_bits}, "
f"Bit di stop {config.stop_bits}, Parità {config.parity}")
print("Premere Ctrl+C per uscire")
# Utilizza `select` per monitorare i dati della porta seriale
while True:
# Attendi l'arrivo dei dati sulla porta seriale
readable, _, _ = select.select([ser.fileno()], [], [], None)
if readable:
# Leggi i dati
data = ser.read(buff_size - 1)
if data:
# Prova a decodificare come stringa, mostra il valore esadecimale in caso di errore
try:
text = data.decode('utf-8')
except UnicodeDecodeError:
text = f"[Dati binari] {data.hex()}"
print(f"Ricevuti {len(data)} byte: {text}")
# Invia i dati in eco
ser.write(data)
except serial.SerialException as e:
print(f"Errore seriale: {e}")
sys.exit(1)
except KeyboardInterrupt:
print("\nInterruzione da parte dell'utente, uscita")
finally:
if 'ser' in locals() and ser.is_open:
ser.close()
print("Porta seriale chiusa")
if __name__ == "__main__":
main()
Per prima cosa, installa la dipendenza: pip install pyserial
Test RS485-1: python uart_example.py /dev/ttyS3
3. DI
L'EC700 dispone di un canale di ingresso digitale per il rilevamento di segnali a contatto pulito, corrispondente ai terminali DIN+ e DIN-.
| Interfaccia hardware | Indice IO |
|---|---|
| DI-1 | 130 |
3.1 Test rapido
#!/bin/bash
Test # EC700 DI (ingresso digitale)
Utilizzo di #: bash di_example.sh
Esempio di #: bash di_example.sh 130
if [ $# -lt 1 ]; then
echo "Utilizzo: bash $0 "
echo "Esempio: bash $0 130"
exit 1
fi
GPIO=$1
GPIO_PATH=/sys/class/gpio/gpio${GPIO}
echo "Test EC700 DI - GPIO $GPIO"
echo "--------------------------"
Esportazione GPIO #
if [ ! -d "$GPIO_PATH" ]; then
echo "$GPIO" > /sys/class/gpio/export 2>/dev/null
sleep 0.1
fi
if [ ! -d "$GPIO_PATH" ]; then
echo "ERRORE: Impossibile esportare il GPIO $GPIO"
exit 1
fi
# Imposta la direzione su ingresso
echo "in" > ${GPIO_PATH}/direction
echo ""
echo "Lettura del valore DI..."
echo "Cortocircuito DIN+ a 3,3 V -> valore=1"
echo "Cortocircuito DIN+ a GND -> valore=0"
echo "Premere Ctrl+C per interrompere"
echo ""
# Ciclo di lettura
while true; do
VAL=$(cat ${GPIO_PATH}/value 2>/dev/null)
if [ "$VAL" != "$LAST" ]; then
echo "[$(data +%H:%M:%S)] DI = $VAL"
LAST=$VAL
fi
sleep 0.2
done
Esegui: bash di_example.sh 130
Dopo aver eseguito lo script, cortocircuitare o aprire ripetutamente DIN+ e DIN- per osservare le variazioni dello stato degli ingressi digitali.
3.2 Esempio di codice in C
/*
* EC700 DI (Digital Input) Test
* Usage: ./di_example <GPIO_NUM>
* Example: ./di_example 130
*
* Connect DIN+ to 3.3V -> reads 1
* Connect DIN+ to GND -> reads 0
* Ctrl+C to stop
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <time.h>
static int keep_running = 1;
static void sig_handler(int sig)
{
(void)sig;
keep_running = 0;
}
/* return 0 on success, -1 on error */
static int gpio_write_file(const char *path, const char *value)
{
int fd = open(path, O_WRONLY);
if (fd < 0) {
perror("open");
return -1;
}
if (write(fd, value, strlen(value)) < 0) {
perror("write");
close(fd);
return -1;
}
close(fd);
return 0;
}
/* return value char on success, -1 on error */
static int gpio_read_value(const char *path)
{
char buf[4] = {0};
int fd = open(path, O_RDONLY);
if (fd < 0) {
perror("open");
return -1;
}
if (read(fd, buf, sizeof(buf) - 1) < 0) {
perror("read");
close(fd);
return -1;
}
close(fd);
return buf[0];
}
int main(int argc, char *argv[])
{
int gpio;
char path[128];
char export_str[16];
int last_val = -1;
if (argc < 2) {
fprintf(stderr, "Usage: %s <GPIO_NUM>\n", argv[0]);
fprintf(stderr, "Example: %s 130\n", argv[0]);
return 1;
}
gpio = atoi(argv[1]);
if (gpio < 0 || gpio > 512) {
fprintf(stderr, "Invalid GPIO number: %d\n", gpio);
return 1;
}
signal(SIGINT, sig_handler);
signal(SIGTERM, sig_handler);
printf("EC700 DI Test - GPIO %d\n", gpio);
printf("--------------------------\n");
/* Export GPIO */
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d", gpio);
if (access(path, F_OK) != 0) {
snprintf(export_str, sizeof(export_str), "%d", gpio);
if (gpio_write_file("/sys/class/gpio/export", export_str) < 0) {
fprintf(stderr, "ERROR: Cannot export GPIO %d\n", gpio);
return 1;
}
usleep(100000); /* 100ms settle time */
}
/* Set direction to input */
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/direction", gpio);
if (gpio_write_file(path, "in") < 0) {
fprintf(stderr, "ERROR: Cannot set GPIO %d to input\n", gpio);
return 1;
}
printf("\nReading DI value...\n");
printf("Short DIN+ to 3.3V -> value=1\n");
printf("Short DIN+ to GND -> value=0\n");
printf("Press Ctrl+C to stop\n\n");
/* Read loop */
while (keep_running) {
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", gpio);
int val = gpio_read_value(path);
if (val < 0) {
fprintf(stderr, "ERROR: Cannot read GPIO %d value\n", gpio);
break;
}
if (val != last_val) {
time_t now = time(NULL);
struct tm *tm_info = localtime(&now);
printf("[%02d:%02d:%02d] DI = %c\n",
tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec,
val);
fflush(stdout);
last_val = val;
}
usleep(10000); /* 10ms */
}
/* Unexport */
printf("\nCleaning up...\n");
snprintf(export_str, sizeof(export_str), "%d", gpio);
gpio_write_file("/sys/class/gpio/unexport", export_str);
printf("Done.\n");
return 0;
}
Compilazione: gcc di_example.c -o di_example
Esegui: ./di_example 130
3.3 Esempio di codice Python
#!/usr/bin/env python3
"""
Test EC700 DI (ingresso digitale)
Utilizzo: python3 di_example.py
Esempio: python3 di_example.py 130
Collegare DIN+ a 3,3 V -> viene letto 1
Collegare DIN+ a GND -> viene letto 0
Premere Ctrl+C per interrompere
"""
import sys
import os
import time
GPIO_BASE = "/sys/class/gpio"
def gpio_export(num):
path = os.path.join(GPIO_BASE, "export")
with open(path, "w") as f:
f.write(str(num))
def gpio_unexport(num):
path = os.path.join(GPIO_BASE, "unexport")
with open(path, "w") as f:
f.write(str(num))
def gpio_set_direction(num, direction):
path = os.path.join(GPIO_BASE, f"gpio{num}", "direction")
with open(path, "w") as f:
f.write(direction)
def gpio_read_value(num):
path = os.path.join(GPIO_BASE, f"gpio{num}", "value")
with open(path, "r") as f:
return f.read().strip()
def main():
if len(sys.argv) < 2:
print(f"Uso: python3 {sys.argv[0]} ")
print(f"Esempio: python3 {sys.argv[0]} 130")
sys.exit(1)
gpio = int(sys.argv[1])
gpio_path = os.path.join(GPIO_BASE, f"gpio{gpio}")
print(f"Test EC700 DI - GPIO {gpio}")
print("-" * 26)
# Esportazione GPIO
if not os.path.exists(gpio_path):
try:
gpio_export(gpio)
time.sleep(0.1)
except Exception as e:
print(f"ERRORE: Impossibile esportare il GPIO {gpio}: {e}")
sys.exit(1)
if not os.path.exists(gpio_path):
print(f"ERRORE: esportazione del GPIO {gpio} non riuscita")
sys.exit(1)
# Imposta direzione
try:
gpio_set_direction(gpio, "in")
except Exception as e:
print(f"ERRORE: Impossibile impostare il GPIO {gpio} come ingresso: {e}")
gpio_unexport(gpio)
sys.exit(1)
print()
print("Lettura del valore DI...")
print("Cortocircuito tra DIN+ e 3,3 V -> valore=1")
print("Cortocircuito tra DIN+ e GND -> valore=0")
print("Premere Ctrl+C per interrompere")
print()
last_val = None
try:
while True:
val = gpio_read_value(gpio)
if val != last_val:
now = time.strftime("%H:%M:%S", time.localtime())
print(f"[{now}] DI = {val}")
last_val = val
time.sleep(0.01)
except KeyboardInterrupt:
pass
except Exception as e:
print(f"ERRORE: {e}")
finally:
print("\nPulizia in corso...")
try:
gpio_unexport(gpio)
except Exception:
pass
print("Fatto.")
if __name__ == "__main__":
main()
Esegui: python di_example.py 130
4. DA FARE
L'EC700 offre due canali di uscita a relè che supportano un'uscita a contatto pulito normalmente aperto per relè industriali, utilizzata per controllare gli stati di accensione e spegnimento dei circuiti esterni. Interfaccia hardware:
| IO | Indice IO | Numero IO | Chip Group |
|---|---|---|---|
| DO-1 | 129 | GPIO4_A | gpiochip1 |
| DO-2 | 128 | GPIO4_A | gpiochip0 |
4.1 Test rapido
#!/bin/bash
# Test DO (uscita digitale) EC700
# Modalità d'uso: bash do_example.sh
# DOUT1: bash do_example.sh 129 on
# DOUT2: bash do_example.sh 128 off
if [ $# -lt 1 ]; then
echo "Uso: bash $0 [on|off]"
echo " GPIO: 129=DOUT1 128=DOUT2"
echo " Se on/off viene omesso: commuta"
exit 1
fi
GPIO=$1
GPIO_PATH=/sys/class/gpio/gpio${GPIO}
# Esportazione
if [ ! -d "$GPIO_PATH" ]; then
echo "$GPIO" > /sys/class/gpio/export 2>/dev/null
sleep 0.1
fi
# Imposta direzione
echo "out" > ${GPIO_PATH}/direction 2>/dev/null
# Leggi valore corrente
CUR=$(cat ${GPIO_PATH}/value 2>/dev/null)
if [ $# -ge 2 ]; then
case "$2" in
on|1) VAL=1 ;;
off|0) VAL=0 ;;
*) echo "Non valido: $2 (utilizzare on/off o 1/0)"; exit 1 ;;
esac
else
# Inverti
if [ "$CUR" = "1" ]; then VAL=0; else VAL=1; fi
fi
echo "$VAL" > ${GPIO_PATH}/value
CUR=$(cat ${GPIO_PATH}/value)
[ "$CUR" = "1" ] && STATE="ON (relè chiuso)" || STATE="OFF (relè aperto)"
echo "DOUT GPIO=$1 -> $STATE"
# Pulizia
echo "$GPIO" > /sys/class/gpio/unexport 2>/dev/null
Compilazione: gcc do_example.c -o do_example
Esegui: ./do_example 129 on
4.2 Esempio di codice in C
/*
* Test EC700 DO (uscita digitale)
* Modalità d'uso: ./do_example [on|off]
* GPIO 129 = DOUT1 128 = DOUT2
* Senza on/off: commuta
*/
#include
#include
#include
#include
#include
static int gpio_write_file(const char *path, const char *value)
{
int fd = open(path, O_WRONLY);
if (fd < 0) { perror("open"); return -1; }
if (write(fd, value, strlen(value)) < 0) { perror("write"); close(fd); return -1; }
close(fd);
return 0;
}
static int gpio_read_value(const char *path)
{
char buf[4] = {0};
int fd = open(path, O_RDONLY);
if (fd < 0) { perror("open"); return -1; }
if (read(fd, buf, sizeof(buf) - 1) < 0) { perror("read"); close(fd); return -1; }
close(fd);
return buf[0];
}
int main(int argc, char *argv[])
{
int gpio, val;
char path[128], export_str[16], val_str[2];
if (argc < 2) {
fprintf(stderr, "Uso: %s [on|off]\n", argv[0]);
fprintf(stderr, " GPIO 129=DOUT1 128=DOUT2\n");
fprintf(stderr, " Senza on/off: commuta\n");
return 1;
}
gpio = atoi(argv[1]);
snprintf(export_str, sizeof(export_str), "%d", gpio);
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d", gpio);
/* Esportazione */
if (access(path, F_OK) != 0) {
gpio_write_file("/sys/class/gpio/export", export_str);
usleep(100000);
}
/* Imposta direzione */
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/direction", gpio);
gpio_write_file(path, "out");
/* Leggi il valore attuale */
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", gpio);
int cur = gpio_read_value(path);
if (argc >= 3) {
if (strcmp(argv[2], "on") == 0 || strcmp(argv[2], "1") == 0)
val = 1;
else if (strcmp(argv[2], "off") == 0 || strcmp(argv[2], "0") == 0)
val = 0;
else {
fprintf(stderr, "Valore non valido: %s (utilizzare on/off o 1/0)\n", argv[2]);
gpio_write_file("/sys/class/gpio/unexport", export_str);
return 1;
}
} else {
val = (cur == '1') ? 0 : 1; /* inverti */
}
snprintf(val_str, sizeof(val_str), "%d", val);
gpio_write_file(path, val_str);
cur = gpio_read_value(path);
printf("DOUT GPIO=%d -> %s (%s)\n", gpio,
(cur == '1') ? "ON (relè chiuso)" : "OFF (relè aperto)",
(cur == '1') ? "COM-NO chiuso" : "COM-NO aperto");
/* Rimuovi dall'esportazione */
gpio_write_file("/sys/class/gpio/unexport", export_str);
return 0;
}
4.3 Esempio di codice Python
#!/usr/bin/env python3
"""
Test DO (uscita digitale) EC700
Utilizzo: python3 do_example.py [on|off]
GPIO 129 = DOUT1 128 = DOUT2
Senza on/off: commutazione
"""
import sys
import os
import time
GPIO_BASE = "/sys/class/gpio"
def gpio_export(num):
with open(os.path.join(GPIO_BASE, "export"), "w") as f:
f.write(str(num))
def gpio_unexport(num):
with open(os.path.join(GPIO_BASE, "unexport"), "w") as f:
f.write(str(num))
def gpio_set_direction(num, direction):
path = os.path.join(GPIO_BASE, f"gpio{num}", "direction")
with open(path, "w") as f:
f.write(direction)
def gpio_write_value(num, value):
path = os.path.join(GPIO_BASE, f"gpio{num}", "value")
with open(path, "w") as f:
f.write(str(value))
def gpio_read_value(num):
path = os.path.join(GPIO_BASE, f"gpio{num}", "value")
with open(path, "r") as f:
return f.read().strip()
def main():
if len(sys.argv) < 2:
print(f"Uso: python3 {sys.argv[0]} [on|off]")
print(" GPIO 129=DOUT1 128=DOUT2")
print(" Senza on/off: toggle")
sys.exit(1)
gpio = int(sys.argv[1])
gpio_path = os.path.join(GPIO_BASE, f"gpio{gpio}")
Esportazione #
if not os.path.exists(gpio_path):
try:
gpio_export(gpio)
time.sleep(0.1)
except Exception as e:
print(f"ERRORE: esportazione GPIO {gpio}: {e}")
sys.exit(1)
# Imposta direzione
gpio_set_direction(gpio, "out")
# Leggi valore attuale
cur = gpio_read_value(gpio)
if len(sys.argv) >= 3:
arg = sys.argv[2].lower()
if arg in ("on", "1"):
val = 1
elif arg in ("off", "0"):
val = 0
else:
print(f"Valore non valido: {arg} (utilizzare on/off o 1/0)")
gpio_unexport(gpio)
sys.exit(1)
else:
val = 0 se cur == "1" altrimenti 1 # toggle
gpio_write_value(gpio, val)
cur = gpio_read_value(gpio)
if cur == "1":
state = "ON (relè chiuso) COM-NO chiuso"
else:
state = "OFF (relè aperto) COM-NO aperto"
print(f"DOUT GPIO={gpio} -> {state}")
gpio_unexport(gpio)
if __name__ == "__main__":
main()
Esegui: python do_example.py 129 in esecuzione
5. Porte Ethernet
Le porte Ethernet sono suddivise in WAN e LAN, gestito dal servizio di rete interna. La configurazione avviene tramite il web. Vedi: [Guida rapida / Preparazione del computer industriale ARM serie EC].
6. Rete cellulare wireless (opzionale)
Il prodotto EC700 supporta la comunicazione 4G/5G (si prega di contattare servizio clienti per l'acquisto di moduli di comunicazione 4G/5G). L'identificazione del modulo e la composizione del numero vengono gestite internamente, senza richiedere alcun intervento da parte dell'utente. Per ulteriori dettagli, consultare: [Guida rapida / Preparazione del computer industriale ARM serie EC]
Nota: la scheda SIM non supporta la sostituzione a caldo. Spegnere il dispositivo prima di inserire o rimuovere la scheda SIM.
7. Wi-Fi (opzionale)
L'EC700 supporta sia la modalità hotspot Wi-Fi che quella client Wi-Fi (consultare servizio clienti (per l'acquisto di moduli WiFi). Supporta 2,4 GHz e 5 GHz bande. Il WiFi è gestito dal programma interno — non è richiesto alcun intervento da parte dell'utente. Si prega di fare riferimento a: [Guida rapida / Preparazione del computer industriale ARM serie EC]
8. Bluetooth (opzionale)
La serie di prodotti EC300 supporta la funzionalità Bluetooth.
8.1 Test rapido
# 1. Visualizza lo stato dell'hardware Bluetooth locale hciconfig -a # 2. Accedi alla console interattiva Bluetooth bluetoothctl # Inizializzazione del Bluetooth, essenziale per l’accoppiamento # Accensione del controller Bluetooth power on # Attivazione dell’agente di accoppiamento per gestire le finestre di dialogo di accoppiamento e i codici di verifica agent on # Impostazione come agente predefinito default-agent # Attivare la scansione, attendere che venga visualizzato il messaggio [NEW] Device AA:BB:CC:DD:EE:FF (dispositivo di destinazione) prima di procedere all’accoppiamento scan on # Cancellare la cache dei dispositivi accoppiati in precedenza (opzionale, risolve anomalie della cache) rimuovi AA:BB:CC:DD:EE:FF # Avvia l’accoppiamento, conferma digitando «yes» nella finestra pop-up; il codice PIN è solitamente 0000/1234 accoppia AA:BB:CC:DD:EE:FF # Considera attendibile il dispositivo per supportare la riconnessione automatica considera attendibile AA:BB:CC:DD:EE:FF # Stabilisci la connessione Bluetooth connetti AA:BB:CC:DD:EE:FF # Disattiva la scansione per impedire il sovraccarico del log disattiva scansione # Eseguire il debug dei comandi di interrogazione # Visualizzare tutti i dispositivi rilevati devices # Visualizzare tutti i dispositivi accoppiati paired-devices # Visualizzare i dispositivi attualmente connessi connections # Visualizzare i protocolli completi e lo stato di connessione del dispositivo di destinazione info AA:BB:CC:DD:EE:FF # Disconnetti il dispositivo disconnect AA:BB:CC:DD:EE:FF # Spegni il Bluetooth (esegui all’occorrenza) power off # Esci dalla console Bluetooth exit
9. Audio
L'EC700 è dotato di un jack da 3,5 mm per cuffie, che consente la registrazione tramite microfono e la riproduzione tramite altoparlanti.
9.1 Test rapido
#Registrazione # Registra 10 secondi di audio arecord -D hw:1,0 -f cd -t wav test.wav -d 10 #Riproduzione: #Inserisci il comando per aprire la console di debug audio alsamixer #Premi F6 per selezionare default:1 rockchip-es8388 #Premi Invio per confermare #Assicurarsi che sia impostato su [00], premere il tasto M per cambiare lo stato #Utilizzare il seguente comando per riprodurre l'audio nella cartella corrente aplay -D hw:1,0 test.wav
10. Display
10.1 Uscita HDMI
L'EC700 supporta un'uscita video fino a 4K a 60 fps.
Uscita video: Collegare un monitor alla porta HDMI. Il dispositivo regola automaticamente la risoluzione all'avvio. Se si verificano problemi di visualizzazione, provare a impostare la risoluzione del monitor su 1080P.
Uscita audio: Collegare un monitor dotato di uscita audio alla porta HDMI e utilizzare il lettore multimediale del desktop per effettuare il test:
/userdata/piano2-CoolEdit.mp3
10.2 Ingresso HDMI
Supporta l'ingresso video 1080P60.
Ingresso video:
# Collegare il PC al dispositivo tramite HDMI e utilizzare il seguente comando per verificare che la connessione sia stata stabilita correttamente v4l2-ctl -d /dev/video0 -D # Avviare l'acquisizione delle immagini v4l2-ctl --verbose -d /dev/video0 --set-fmt-video=width=1920,height=1080,pixelformat='BGR3' --stream-mmap=4 --stream-skip=0 --stream-to=~/Desktop/1080P60.bgr --stream-count=50 --stream-poll # Per impostazione predefinita vengono acquisiti 50 fotogrammi. Al termine dell’acquisizione, il file viene salvato come 1080P60.bgr nel percorso ~/Desktop/1080P60.bgr # È possibile utilizzare un visualizzatore di immagini che supporti il formato BGR per aprirlo e verificare se il colore e la risoluzione dell'output sono normali. # Si consiglia di utilizzare il programma 7YUV per la visualizzazione.
Ingresso audio:
# Assicurarsi che il cavo HDMI RX sia collegato tra il PC e il dispositivo, verificare che l'audio sia in riproduzione sul PC e impostare la scheda audio di uscita su RK xxx in Windows 10. # Eseguire il seguente comando sulla scheda per acquisire l’audio in ingresso HDMI RX (la scheda audio predefinita per l’ingresso HDMI RX è hw:0,0): arecord -D hw:0,0 -f dat hdmi_rx.wav # Interrompere l’acquisizione dopo un certo periodo di tempo premendo Ctrl+C. Il file verrà salvato nella directory corrente. # Copiare il file audio hdmi_rx.wav sul PC con Windows 10 per la riproduzione. L’audio dovrebbe corrispondere.
API REST del sistema
L'EC700 mette a disposizione un'API REST per interrogare a livello di programmazione lo stato del dispositivo e della rete. Entrambi gli endpoint accettano OTTIENI richieste senza parametri.
1. Ottenere le informazioni di base sul dispositivo
-
- URL:
GET http://{device_IP}/rpc-api/data/devinfo
- URL:
-
- Metodo: OTTIENI
-
- Parametri della richiesta: Nessuno
Campi di risposta:
| Campo | Descrizione | Tipo | Osservazioni |
|---|---|---|---|
| codice | Codice di stato della risposta | int | Sempre 200 in caso di successo |
| data.model | Modello del dispositivo | stringa | Modello del dispositivo |
| data.sn | Numero di serie del dispositivo | stringa | Numero di serie del dispositivo |
| versione dei dati | Versione del dispositivo | stringa | Numero di versione del software |
Esempio di risposta:
{
"codice": 200,
"dati": {
"modello": "EC700",
"sn": "xxxxxxxxxxxx",
"versione": "x.x.x"
}
}
2. Ottenere le informazioni sulla rete WWAN (cellulare) del dispositivo
- URL:
GET http://{device_IP}/rpc-api/data/wwaninfo - Metodo: OTTIENI
- Parametri della richiesta: Nessuno
Campi di risposta:
| Campo | Descrizione | Tipo | Osservazioni |
|---|---|---|---|
| codice | Codice di stato della risposta | int | Sempre 200 in caso di successo |
| data.enable | Con connessione cellulare | booleano | true = abilitato, false = disabilitato |
| data.status | Stato della connessione dial-up | numero | 0 = acceso, 1 = in fase di inizializzazione, 2 = rilevamento SIM, 3 = PDP attivato, 4 = composizione del numero, 5 = pronto |
| data.ip | Indirizzo IP WWAN | stringa | Indirizzo IP assegnato dalla rete cellulare |
| data.mask | Maschera di sottorete | stringa | Maschera di sottorete |
| data.gateway | Indirizzo del gateway | stringa | Gateway predefinito |
| data.metric | Metrica del percorso | numero | Valore più basso = priorità più alta |
| data.dns | Server DNS | stringa | Indirizzo del resolver DNS |
| versione dei dati | Versione del firmware del modulo | stringa | Versione del firmware del modulo 5G/4G |
| data.imei | IMEI | stringa | Numero IMEI del modulo |
| dati.segnale | Potenza del segnale | numero | 0–100, più alto = segnale più forte |
| data.ccid | ID della scheda SIM | stringa | ICCID della SIM |
| data.operator | Vettore | stringa | Nome del vettore attualmente registrato |
| data.sim.maxcall | Numero massimo di tentativi di ricomposizione | numero | Limite di tentativi in caso di errore di composizione del numero |
| data.sim.sim0.auth | Metodo di autenticazione APN | numero | 0 = Nessuno, 1 = PAP, 2 = CHAP, 3 = PAP/CHAP |
| data.sim.sim0.addr | Indirizzo APN | stringa | Nome del punto di accesso |
| data.sim.sim0.nome | Nome utente APN | stringa | Nome utente per l'autenticazione APN |
| data.sim.sim0.passwd | Password APN | stringa | Password di autenticazione APN |
| data.sim.sim0.pinCode | Codice PIN | stringa | Codice PIN della scheda SIM |
| data.ping.enable | Sonda di rete | booleano | true = abilitato, false = disabilitato |
| data.ping.addr0 | Host della sonda 0 | stringa | Indirizzo di destinazione della sonda di rete 1 |
| data.ping.addr1 | Host della sonda 1 | stringa | Indirizzo di destinazione della sonda di rete 2 |
| data.ping.cyc | Intervallo di sondaggio | numero | Intervallo in secondi |
| data.ping.num | Numero di sonde | numero | Numero di soglie di errore |
| data.ping.stato | Stato della sonda | numero | 255 = non verificato, 0 = fallito, 1 = riuscito |
Esempio di risposta:
{
"code": 200,
"data": {
"enable": true,
"status": 0,
"ip": "",
"mask": "",
"gateway": "",
"metric": 3,
"dns": "223.5.5.5 8.8.8.8",
"version": "",
"imei": "",
"signal": -1,
"ccid": "",
"operator": "",
"sim": {
"maxcall": 5,
"sim0": {
"auth": 3,
"addr": "",
"name": "",
"passwd": "",
"pinCode": ""
},
},
"ping": {
"enable": true,
"addr0": "223.5.5.5",
"addr1": "8.8.8.8",
"cyc": 10,
"num": 3,
"state": 255
}
}
}
Software preinstallato
L'EC700 viene fornito con diversi pacchetti software industriali preinstallati e configurati per l'avvio automatico. Ecco come gestirli.
1. Programma di gestione interna (iotrouter)
Per semplificare l'esperienza utente, la serie EC700 viene fornita con la funzione integrata iotrouter programma di gestione che si avvia all'avvio del sistema. Il programma di gestione comprende:
- Inizializzazione del dispositivo
- Gestione della rete
- Gestione cellulare
- Gestione del WiFi
- Firewall
- Servizio di configurazione dei dispositivi (porta predefinita 80, configurabile; file:
/usr/local/src/iotrouter/web/user-config.js) - Esploratore di file (percorso predefinito:
/run/media/; configurabile; file:/usr/local/src/iotrouter/web/user-config.js)
Nota: si consiglia di lasciare in esecuzione il programma interno. Se è necessario disattivarlo, dovrai occuparti personalmente dei servizi di gestione sopra indicati.
2. NeuronEX
L'EC700 viene fornito con NeuronEX-Lite preinstallato. Il servizio si avvia automaticamente all'avvio del sistema e ascolta sulla porta 8085.
Per un'introduzione, si veda: [Percorso di apprendimento dei computer industriali ARM della serie EC]
Visualizza lo stato del servizio: systemctl status neuronex
Riavvia il servizio: systemctl restart neuronex
Sospensione del servizio: systemctl stop neuronex
Disattiva l'avvio automatico: systemctl disable neuronex
3. Node-RED
L'EC700 viene fornito con Node-RED preinstallato. Il servizio si avvia automaticamente all'avvio del sistema e rimane in ascolto sulla porta 1880. Per un'introduzione, si veda: [Percorso di apprendimento dei computer industriali ARM della serie EC]
Visualizza lo stato del servizio: systemctl status node-red
Riavvia il servizio: systemctl restart node-red
Sospensione del servizio: systemctl stop node-red
Disattiva l'avvio automatico: systemctl disable node-red
4. FUXA
Tutti i prodotti della serie EC700 sono dotati di FUXA preinstallato. Il servizio si avvia automaticamente all'avvio del sistema e ascolta sulla porta 1881. Per un'introduzione, si veda: [Guida allo sviluppo avanzato per i computer industriali ARM della serie EC]
Visualizza lo stato del servizio: systemctl status fuxa
Riavvia il servizio: systemctl restart fuxa
Sospensione del servizio: systemctl stop fuxa
Disattiva l'avvio automatico: systemctl disable fuxa
5. Desktop Xfce4
L'ambiente desktop predefinito è Xfce4. Viene fornito solo a scopo dimostrativo. Se hai bisogno di visualizzare altri contenuti, come un'interfaccia utente basata su Qt, puoi svilupparla autonomamente.
Il gestore di visualizzazione è: lightdm
Visualizza lo stato del servizio: systemctl status lightdm
Riavvia il servizio: systemctl restart lightdm
Sospensione del servizio: systemctl stop lightdm
Disattiva l'avvio automatico: systemctl disable lightdm
6. Programmi utente personalizzati
Le applicazioni utente vengono sviluppate autonomamente dagli utenti e vengono eseguite come processi separati. Tuttavia, è necessario prestare particolare attenzione alla gestione della memoria e dello spazio di archiviazione per evitare eccezioni di sistema. È possibile configurare il software in modo che venga avviato automaticamente dal sistema utilizzando i seguenti metodi:
/etc/rc.local- servizio systemd
/etc/init.dsistema
Offriamo inoltre servizi di sviluppo software su misura. Per richieste di informazioni, ti preghiamo di contattare il nostro team commerciale.
7. Personalizzazione del logo di avvio
Gli utenti possono sostituire autonomamente il logo di avvio del sistema.
| File del logo | Palcoscenico |
|---|---|
| logo.bmp | Visualizzato durante la fase U-Boot |
| logo_kernel.bmp | Visualizzato durante la fase di avvio del kernel |
7.1 Requisiti di formattazione
L'immagine del logo deve essere un Immagine bitmap BMP a 24 bit. La risoluzione dell'immagine non deve superare quella dello schermo HDMI collegato.
7.2 Sostituzione del logo
- Accendere il dispositivo.
- Copia la tua personalizzazione
logo.bmpelogo_kernel.bmpfile nelSDK_PATH/kernel-6.1directory, sostituendo i file esistenti con lo stesso nome.

Nota: i nomi dei file contenenti i loghi non devono essere modificati.
Conclusione
L'EC700 è progettato per consentirti di passare rapidamente dall'idea iniziale al prototipo funzionante. Grazie all’ambiente Linux aperto, allo stack software industriale preinstallato (Node-RED, NeuronEX, FUXA) e alle interfacce hardware intuitive, la maggior parte del lavoro di base è già stata svolta: basta scrivere la logica dell’applicazione e collegare sensori e attuatori.
Ecco alcuni aspetti da tenere a mente quando inizi a sviluppare:
- Inizia dalla porta seriale di debug. Anche se prevedi di lavorare tramite SSH, la porta di debug Type-C è la soluzione di riserva da utilizzare quando la rete non funziona correttamente.
- Sfrutta l'API REST. Il
/rpc-api/data/Gli endpoint rendono semplicissimo importare le informazioni sui dispositivi e lo stato della rete cellulare nelle proprie dashboard o nei propri script di monitoraggio — senza bisogno di analizzare manualmente i comandi AT. - Rispettare il servizio iotrouter. Si occupa della gestione della rete, del Wi-Fi e della connessione cellulare in background. Se lo disattivi, dovrai provvedere tu stesso a reimplementare tali funzioni.
- Tieni d'occhio il budget destinato allo spazio di archiviazione. Con 128 GB di memoria integrata e la possibilità di espansione NVMe, hai spazio a sufficienza — ma le immagini Docker e i pesi dei modelli di IA si accumulano rapidamente.
Se stai cercando le specifiche hardware complete, la tabella di compatibilità dei protocolli o le opzioni di personalizzazione OEM/ODM, consulta la Pagina del prodotto EC700. Per qualsiasi domanda relativa all'accesso all'SDK, allo sviluppo personalizzato o agli ordini all'ingrosso, il team di IOTRouter è a vostra disposizione: basta contattarci tramite il modulo di contatto presente sul sito.
Agnes Wang è una specialista in soluzioni IoT presso IOTRouter, dove si occupa principalmente di gateway IoT industriali, edge computing e soluzioni di automazione industriale.
È specializzata in tecnologie di comunicazione industriale, tra cui Modbus, IEC 60870-5-104, MQTT, OPC UA, integrazione di PLC e applicazioni di monitoraggio remoto. Collabora alla stesura di articoli tecnici e guide applicative riguardanti soluzioni IoT industriali, conversione di protocolli ed edge computing.
- Agnes Wang
- Agnes Wang
- Agnes Wang



