Índice
AlternarEste guia ajuda os programadores a começarem rapidamente a trabalhar com o EC700 — abordando a comunicação através da porta série, o controlo de E/S digitais, a integração da API REST, a gestão do software pré-instalado e a personalização do logótipo de arranque.
O EC700 é um PC industrial para computação de ponta com IA, equipado com o processador Rockchip RK3588J e uma NPU integrada de 6 TOPS, concebido para a inferência de IA no próprio dispositivo. É frequentemente utilizado na produção inteligente, na inspeção por visão industrial e noutros cenários de IA. Consulte a ficha técnica completa em Página do produto EC700.
Prerequisites and Tools for EC700 Developments
Este guia aplica-se ao gateway EC700. Antes de começar, certifique-se de que tem as seguintes ferramentas à mão. Faça o download das seguintes ferramentas através do página de downloads.
Cliente SSH
Recomenda-se o MobaXterm, mas também pode utilizar qualquer cliente SSH com o qual esteja familiarizado.
Ferramenta de depuração em série
Recomenda-se o uso do XCOM, mas também pode utilizar qualquer terminal de série que preferir.
Acessórios de hardware
Entre as ferramentas auxiliares de depuração mais comuns contam-se os adaptadores USB para RS485, os cabos Ethernet, etc. Por favor, prepare-os você mesmo.
Cadeia de ferramentas de compilação cruzada
Se estiver a compilar aplicações nativas em C/C++ num PC anfitrião e a implementá-las no EC700.
Ambiente de software
O EC700 vem equipado com um ambiente Linux totalmente integrado. Eis o que está a funcionar nos bastidores:
| Software | Versão |
|---|---|
| SO | Linux incorporado |
| Kernel | Linux 6.1.118 |
| Node.js | v22.17.0 |
| Python | Python 3.10.12 |
| Concha | bash |
| Docker | V27.4.1 |
| Qt | V5.15.3 |
| Ambiente de trabalho | Xfce4 |
Recursos do dispositivo
| Categoria | Detalhes | Observações |
|---|---|---|
| Armazenamento | 128 GB no total | ~108 GB de espaço livre de fábrica; expansível através de cartão SD ou SSD M.2 NVMe |
| Memória | 8 GB | ~6 GB de espaço livre de fábrica |
| CPU | RK3588 | ~98% em modo de espera logo ao sair da embalagem |
| NPU | 6 TOPS | ~100% em modo de espera logo ao sair da embalagem |
Interfaces periféricas
1. Porta de depuração
O EC700 disponibiliza a porta série de depuração do sistema através de um Tipo C interface. Utilize estas definições no seu terminal série:
- Velocidade de transmissão: 115 200
- Bits de dados: 8
- Bits de paragem: 1
- Paridade: Nenhuma
- Controlo de fluxo: Nenhum
- Nome de utilizador predefinido: root
- Palavra-passe predefinida: Consulte a documentação sobre permissões do sistema aberto.
2. Portas seriais (RS485 / RS232)
O EC700 dispõe de dois canais RS485 e um canal RS232:
| Interface de hardware | Ficheiro do dispositivo |
|---|---|
| RS485-1 | /dev/ttyS3 (corresponde a A1 / B1) |
| RS485-2 | /dev/ttyS4 (corresponde a A2 / B2) |
| RS232 | /dev/ttyS1 (corresponde a TXD / RTD) |
Nota: As portas RS485 utilizam controlo automático de direção. Não é necessário alternar manualmente entre os modos de transmissão e receção — o hardware trata disso automaticamente.
2.1 Teste rápido
Utilize o minicom utilitário para testes. Consulte os recursos online ou o GPT/Google para obter detalhes sobre a sua utilização.
2.2 Exemplo de código em C
#include
#include
#include
#include
#include
#include
#include
#include
#define BUFFER_SIZE 256
typedef struct {
int baud_rate; // Velocidade de transmissão
int data_bits; // Bits de dados (5, 6, 7, 8)
int stop_bits; // Bits de paragem (1,2)
char parity; // Bit de paridade (N: Nenhuma, O: Ímpar, E: Par)
} 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;
padrão:
fprintf(stderr, "Velocidade de transmissão não suportada, a utilizar 115200\n");
velocidade = B115200;
}
cfsetispeed(&tty, velocidade);
cfsetospeed(&tty, velocidade);
// Definir bits de dados
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, "Bits de dados não suportados, a utilizar 8\n");
tty.c_cflag |= CS8;
}
// Definir bits de paragem
if (config->stop_bits == 2) {
tty.c_cflag |= CSTOPB;
} else {
tty.c_cflag &= ~CSTOPB;
}
// Definir o bit de paridade
switch (config->parity) {
case 'N': case 'n':
tty.c_cflag &= ~PARENB; // Nenhuma
break;
case 'O': case 'o':
tty.c_cflag |= PARENB; // Ímpar
tty.c_cflag |= PARODD;
break;
case 'E': case 'e':
tty.c_cflag |= PARENB; // Par
tty.c_cflag &= ~PARODD;
break;
default:
fprintf(stderr, "Paridade não suportada, a utilizar N\n");
tty.c_cflag &= ~PARENB;
}
// Outras configurações
tty.c_cflag |= (CLOCAL | CREAD); // Ativar o modo recetor e local
tty.c_cflag &= ~CRTSCTS; // Desativar o controlo de fluxo por hardware
tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // Modo de entrada bruta
tty.c_oflag &= ~OPOST; // Modo de saída bruta
tty.c_cc[VMIN] = 1; // Número mínimo de caracteres a ler
tty.c_cc[VTIME] = 0; // Tempo limite de leitura (unidade: 0,1 segundos)
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, "Utilização: %s \n", argv[0]);
exit(EXIT_FAILURE);
}
portname = argv[1];
// Configurar os parâmetros da porta série
SerialConfig config = {
.baud_rate = 115200, // Velocidade de transmissão
.data_bits = 8, // Bits de dados
.stop_bits = 1, // Bits de paragem
.parity = 'N' // Paridade (N: Nenhuma, O: Ímpar, E: Par)
};
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("Teste de eco da porta série a decorrer em %s\n", portname);
printf("Configuração: %d baud, %d bits de dados, %d bit de paragem, %c paridade\n",
config.baud_rate, config.data_bits, config.stop_bits, config.parity);
printf("Prima Ctrl+C para sair.\n");
fd_set readfds;
char buffer[BUFFER_SIZE];
int n;
while (1) {
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
// Aguarda indefinidamente pela chegada de dados (configuração de tempo limite removida)
if (select(fd + 1, &readfds, NULL, NULL, NULL) 0) {
buffer[n] = '\0';
printf("Recebidos %d bytes: %s\n", n, buffer);
// Repetir dados
write(fd, buffer, n);
} else if (n < 0) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
perror("read");
break;
}
}
}
}
close(fd);
return 0;
}
Compilar: gcc rs485_exemplo.c -o rs485_exemplo
Teste RS485-1: ./rs485_example /dev/ttyS3
2.3 Exemplo de código em Python
import serial
import select
import sys
import tty
class SerialConfig:
def __init__(self):
self.baud_rate = 115200 # Velocidade de transmissão
self.data_bits = 8 # Bits de dados
self.stop_bits = 1 # Bits de paragem
self.parity = 'N' # Paridade (N: Nenhuma, O: Ímpar, E: Par)
def set_serial_config(ser, config):
"""Configurar os parâmetros da porta série"""
# Definir taxa de transmissão
ser.baudrate = config.baud_rate
# Definir bits de dados
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: # Valor predefinido para 8 bits
ser.bytesize = serial.EIGHTBITS
# Definir bits de paragem
if config.stop_bits == 2:
ser.stopbits = serial.STOPBITS_TWO
else: # Padrão: 1 bit
ser.stopbits = serial.STOPBITS_ONE
# Definir paridade
if config.parity.upper() == 'O':
ser.parity = serial.PARITY_ODD
elif config.parity.upper() == 'E':
ser.parity = serial.PARITY_EVEN
caso contrário: # Padrão: nenhum
ser.parity = serial.PARITY_NONE
# Desativar controlo de fluxo por hardware
ser.rtscts = False
# Desativar controlo de fluxo por software
ser.xonxoff = False
# Definir tempo de espera
ser.timeout = 0.1 # Tempo de espera de 100 ms
return ser
def main():
if len(sys.argv) < 2:
print(f"Utilização: {sys.argv[0]} ")
print(f"Exemplo: {sys.argv[0]} /dev/ttyS7")
sys.exit(1)
portname = sys.argv[1]
buff_size = 256
# Inicializar configuração serial
config = SerialConfig()
try:
# Abrir porta série
ser = serial.Serial()
ser.port = portname
# Aplicar configuração e abrir porta série
ser = set_serial_config(ser, config)
ser.open()
if not ser.is_open:
print("Falha ao abrir a porta série")
sys.exit(1)
print(f"Porta série {portname} aberta com sucesso")
print(f"Configuração: Velocidade de transmissão {config.baud_rate}, Bits de dados {config.data_bits}, "
f"Bits de paragem {config.stop_bits}, Paridade {config.parity}")
print("Prima Ctrl+C para sair")
# Utilizar o `select` para monitorizar os dados da porta série
while True:
# Aguardar a chegada de dados na porta série
readable, _, _ = select.select([ser.fileno()], [], [], None)
if readable:
# Ler dados
data = ser.read(buff_size - 1)
if data:
# Tentar descodificar como cadeia de caracteres; apresentar em hexadecimal se falhar
try:
text = data.decode('utf-8')
except UnicodeDecodeError:
text = f"[Dados binários] {data.hex()}"
print(f"Recebidos {len(data)} bytes: {text}")
# Enviar dados de volta
ser.write(data)
except serial.SerialException as e:
print(f"Erro de série: {e}")
sys.exit(1)
except KeyboardInterrupt:
print("\nInterrupção do utilizador, a sair")
finally:
if 'ser' in locals() and ser.is_open:
ser.close()
print("Porta série fechada")
if __name__ == "__main__":
main()
Instale primeiro a dependência: pip install pyserial
Teste RS485-1: python uart_example.py /dev/ttyS3
3. DI
O EC700 dispõe de um canal de entrada digital para a deteção de sinais de contacto seco, correspondente aos terminais DIN+ e DIN-.
| Interface de hardware | Índice IO |
|---|---|
| DI-1 | 130 |
3.1 Teste rápido
#!/bin/bash
Teste de entrada digital (DI) do # EC700
Utilização do #: bash di_example.sh
Exemplo do #: bash di_example.sh 130
if [ $# -lt 1 ]; then
echo "Utilização: bash $0 "
echo "Exemplo: bash $0 130"
exit 1
fi
GPIO=$1
GPIO_PATH=/sys/class/gpio/gpio${GPIO}
echo "Teste DI do EC700 - GPIO $GPIO"
echo "--------------------------"
Exportação de 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 "ERRO: Não é possível exportar o GPIO $GPIO"
exit 1
fi
# Definir a direção para entrada
echo "in" > ${GPIO_PATH}/direction
echo ""
echo "A ler o valor de DI..."
echo "Ligar DIN+ a 3,3 V -> valor=1"
echo "Ligar DIN+ a GND -> valor=0"
echo "Prima Ctrl+C para parar"
echo ""
# Ciclo de leitura
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
Executar: bash di_example.sh 130
Após executar o script, ligue ou desligue repetidamente os pinos DIN+ e DIN- para observar as alterações no estado das entradas digitais.
3.2 Exemplo de código em 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;
}
Compilar: gcc di_example.c -o di_example
Executar: ./di_example 130
3.3 Exemplo de código em Python
#!/usr/bin/env python3
"""
Teste de DI (Entrada Digital) do EC700
Utilização: python3 di_example.py
Exemplo: python3 di_example.py 130
Ligar DIN+ a 3,3 V -> lê 1
Ligar DIN+ a GND -> lê 0
Ctrl+C para parar
"""
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"Utilização: python3 {sys.argv[0]} ")
print(f"Exemplo: 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"Teste DI do EC700 - GPIO {gpio}")
print("-" * 26)
# Exportar GPIO
if not os.path.exists(gpio_path):
try:
gpio_export(gpio)
time.sleep(0.1)
except Exception as e:
print(f"ERRO: Não é possível exportar o GPIO {gpio}: {e}")
sys.exit(1)
if not os.path.exists(gpio_path):
print(f"ERRO: Falha na exportação do GPIO {gpio}")
sys.exit(1)
# Definir direção
try:
gpio_set_direction(gpio, "in")
except Exception as e:
print(f"ERRO: Não é possível definir o GPIO {gpio} como entrada: {e}")
gpio_unexport(gpio)
sys.exit(1)
print()
print("A ler o valor DI...")
print("Ligar DIN+ a 3,3 V -> valor=1")
print("Ligar DIN+ em curto a GND -> valor=0")
print("Prima Ctrl+C para parar")
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"ERRO: {e}")
finally:
print("\nA limpar...")
try:
gpio_unexport(gpio)
except Exception:
pass
print("Concluído.")
if __name__ == "__main__":
main()
Executar: python di_example.py 130
4. FAZER
O EC700 dispõe de dois canais de saída de relé que suportam saídas de contacto seco normalmente abertas para relés industriais, utilizadas para controlar os estados de ligar/desligar de circuitos externos. Interface de hardware:
| IO | Índice IO | Número IO | Grupo Chip |
|---|---|---|---|
| DO-1 | 129 | GPIO4_A | gpiochip1 |
| DO-2 | 128 | GPIO4_A | gpiochip0 |
4.1 Teste rápido
#!/bin/bash
Teste de saída digital (DO) do # EC700
Utilização do #: bash do_example.sh
# DOUT1: bash do_example.sh 129 on
# DOUT2: bash do_example.sh 128 off
if [ $# -lt 1 ]; then
echo "Utilização: bash $0 [on|off]"
echo " GPIO: 129=DOUT1 128=DOUT2"
echo " Se on/off for omitido: alterna"
exit 1
fi
GPIO=$1
GPIO_PATH=/sys/class/gpio/gpio${GPIO}
# Exportar
if [ ! -d "$GPIO_PATH" ]; then
echo "$GPIO" > /sys/class/gpio/export 2>/dev/null
sleep 0.1
fi
# Definir direção
echo "out" > ${GPIO_PATH}/direction 2>/dev/null
# Ler valor atual
CUR=$(cat ${GPIO_PATH}/value 2>/dev/null)
if [ $# -ge 2 ]; then
case "$2" in
on|1) VAL=1 ;;
off|0) VAL=0 ;;
*) echo "Inválido: $2 (utilize on/off ou 1/0)"; exit 1 ;;
esac
else
# Alternar
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é fechado)" || STATE="OFF (Relé aberto)"
echo "DOUT GPIO=$1 -> $STATE"
Limpeza do #
echo "$GPIO" > /sys/class/gpio/unexport 2>/dev/null
Compilar: gcc do_example.c -o do_example
Executar: ./do_example 129 em
4.2 Exemplo de código em C
/*
* Teste de saída digital (DO) do EC700
* Utilização: ./do_example [on|off]
* GPIO 129 = DOUT1 128 = DOUT2
* Sem on/off: alternar
*/
#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, "Utilização: %s [on|off]\n", argv[0]);
fprintf(stderr, " GPIO 129=DOUT1 128=DOUT2\n");
fprintf(stderr, " Sem on/off: alternar\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);
/* Exportar */
if (access(path, F_OK) != 0) {
gpio_write_file("/sys/class/gpio/export", export_str);
usleep(100000);
}
/* Definir direção */
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/direction", gpio);
gpio_write_file(path, "out");
/* Ler corrente */
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, "Valor inválido: %s (utilize on/off ou 1/0)\n", argv[2]);
gpio_write_file("/sys/class/gpio/unexport", export_str);
return 1;
}
} else {
val = (cur == '1') ? 0 : 1; /* alternar */
}
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é fechado)" : "OFF (Relé aberto)",
(cur == '1') ? "COM-NO fechado" : "COM-NO aberto");
/* Desexportar */
gpio_write_file("/sys/class/gpio/unexport", export_str);
return 0;
}
4.3 Exemplo de código em Python
#!/usr/bin/env python3
"""
Teste de saída digital (DO) do EC700
Utilização: python3 do_example.py [on|off]
GPIO 129 = DOUT1 128 = DOUT2
Sem on/off: alternar
"""
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"Utilização: python3 {sys.argv[0]} [on|off]")
print(" GPIO 129=DOUT1 128=DOUT2")
print(" Sem on/off: alternar")
sys.exit(1)
gpio = int(sys.argv[1])
gpio_path = os.path.join(GPIO_BASE, f"gpio{gpio}")
# Export
if not os.path.exists(gpio_path):
try:
gpio_export(gpio)
time.sleep(0.1)
except Exception as e:
print(f"ERRO: exportação do GPIO {gpio}: {e}")
sys.exit(1)
# Definir direção
gpio_set_direction(gpio, "out")
# Ler valor atual
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"Valor inválido: {arg} (utilize on/off ou 1/0)")
gpio_unexport(gpio)
sys.exit(1)
else:
val = 0 se cur == "1" senão 1 # alternar
gpio_write_value(gpio, val)
cur = gpio_read_value(gpio)
if cur == "1":
state = "ON (Relé fechado) COM-NO fechado"
else:
state = "OFF (Relé aberto) COM-NO aberto"
print(f"DOUT GPIO={gpio} -> {state}")
gpio_unexport(gpio)
if __name__ == "__main__":
main()
Executar: python do_example.py 129 em
5. Portas Ethernet
As portas Ethernet estão divididas em WAN e LAN, gerido pelo serviço de rede interna. A configuração é efetuada através da Web. Ver: [Guia de Início Rápido / Preparação do Computador Industrial ARM da Série EC].
6. Rede móvel (opcional)
O produto EC700 suporta comunicação 4G/5G (por favor, contacte atendimento ao cliente para adquirir módulos de comunicação 4G/5G). A identificação do módulo e a marcação são geridas internamente, não exigindo qualquer intervenção do utilizador. Para mais detalhes, consulte: [Guia de Início Rápido / Preparação do Computador Industrial ARM da Série EC]
Nota: O cartão SIM não suporta a troca a quente. Desligue o dispositivo antes de inserir ou retirar o cartão SIM.
7. Wi-Fi (opcional)
O EC700 suporta tanto o modo de ponto de acesso Wi-Fi como o modo de cliente Wi-Fi (consulte atendimento ao cliente (para compras de módulos Wi-Fi). É compatível com 2,4 GHz e 5 GHz bandas. O Wi-Fi é gerido pelo programa interno — não é necessária qualquer intervenção do utilizador. Consulte: [Guia de Início Rápido / Preparação do Computador Industrial ARM da Série EC]
8. Bluetooth (opcional)
A série de produtos EC300 suporta a funcionalidade Bluetooth.
8.1 Teste rápido
# 1. Ver o estado do hardware Bluetooth local hciconfig -a # 2. Aceder à consola interativa do Bluetooth bluetoothctl # Inicialização do Bluetooth, essencial para o emparelhamento # Ligar o controlador Bluetooth power on # Ativar o agente de emparelhamento para gerir as janelas pop-up de emparelhamento e os códigos de verificação agent on # Definir como agente predefinido default-agent # Ativar a pesquisa; aguarde que o dispositivo de destino [NOVO] AA:BB:CC:DD:EE:FF seja apresentado antes do emparelhamento scan on # Limpar a cache de emparelhamento de dispositivos antigos (opcional; resolve anomalias na cache) remover AA:BB:CC:DD:EE:FF # Iniciar o emparelhamento, confirmar digitando «yes» na janela pop-up; o código PIN é normalmente 0000/1234 emparelhar AA:BB:CC:DD:EE:FF # Marcar o dispositivo como de confiança para permitir a reconexão automática trust AA:BB:CC:DD:EE:FF # Estabelecer ligação Bluetooth connect AA:BB:CC:DD:EE:FF # Desativar a pesquisa para impedir o excesso de registos scan off # Depurar comandos de consulta # Ver todos os dispositivos detetados dispositivos # Ver todos os dispositivos emparelhados dispositivos-emparelhados # Ver os dispositivos atualmente ligados ligações # Ver os protocolos completos e o estado da ligação do dispositivo de destino info AA:BB:CC:DD:EE:FF # Desligar a ligação do dispositivo desligar AA:BB:CC:DD:EE:FF # Desligar o Bluetooth (executar conforme necessário) desligar # Sair da consola Bluetooth sair
9. Áudio
O EC700 dispõe de uma tomada de 3,5 mm para auscultadores, que permite a gravação através do microfone e a reprodução através dos altifalantes.
9.1 Teste rápido
#Gravação # Gravar 10 segundos de áudio arecord -D hw:1,0 -f cd -t wav test.wav -d 10 #Reprodução: #Introduza o comando para abrir a consola de depuração de som alsamixer #Prima F6 para selecionar default:1 rockchip-es8388 #Prima Enter para confirmar #Certifique-se de que está definido como [00]; prima a tecla M para alternar o estado #Utilize o seguinte comando para reproduzir o áudio na pasta atual aplay -D hw:1,0 test.wav
10. Ecrã
10.1 Saída HDMI
A EC700 suporta uma saída de vídeo até 4K a 60 fps.
Saída de vídeo: Ligue um monitor à porta HDMI. O dispositivo ajusta automaticamente a resolução no arranque. Se surgirem problemas de visualização, tente alterar a resolução do monitor para 1080P.
Saída de áudio: Ligue um monitor com saída de áudio à porta HDMI e utilize o reprodutor multimédia do ambiente de trabalho para testar:
/userdata/piano2-CoolEdit.mp3
10.2 Entrada HDMI
Suporta entrada de vídeo 1080P60.
Entrada de vídeo:
# Ligue o PC ao dispositivo através de HDMI e utilize o seguinte comando para verificar se a ligação foi bem-sucedida v4l2-ctl -d /dev/video0 -D # Inicie a captura de imagens 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 # Captura 50 fotogramas por predefinição. Após a conclusão da captura, o ficheiro é guardado como 1080P60.bgr no caminho ~/Desktop/1080P60.bgr # Pode utilizar um visualizador de imagens compatível com BGR para o abrir e verificar se a cor e a resolução da saída estão normais. # Recomenda-se a utilização do programa 7YUV para visualização.
Entrada de áudio:
# Certifique-se de que o cabo HDMI RX está ligado entre o PC e o dispositivo, verifique se o áudio está a ser reproduzido no PC e defina a placa de som de saída como RK xxx no Windows 10. # Execute o seguinte comando na placa para capturar a entrada de áudio HDMI RX (a placa de som de entrada HDMIRX predefinida é hw:0,0): arecord -D hw:0,0 -f dat hdmi_rx.wav # Interrompa a captura após algum tempo premindo Ctrl+C. O ficheiro será guardado no diretório atual. # Copie o ficheiro de áudio hdmi_rx.wav para o PC com Windows 10 para reprodução. O som deverá corresponder.
API REST do sistema
O EC700 disponibiliza uma API REST para consultar o estado do dispositivo e da rede através de código. Ambos os pontos de extremidade aceitam OBTER solicitações sem parâmetros.
1. Obter informações básicas sobre o dispositivo
-
- URL:
OBTER http://{device_IP}/rpc-api/data/devinfo
- URL:
-
- Método: OBTER
-
- Parâmetros da solicitação: Nenhum
Campos de resposta:
| Campo | Descrição | Tipo | Observações |
|---|---|---|---|
| código | Código de estado da resposta | int | Sempre 200 em caso de sucesso |
| data.model | Modelo do dispositivo | cadeia de caracteres | Modelo do dispositivo |
| data.sn | Número de série do dispositivo | cadeia de caracteres | Número de série do dispositivo |
| data.versão | Versão do dispositivo | cadeia de caracteres | Número da versão do software |
Exemplo de resposta:
{
"código": 200,
"dados": {
"modelo": "EC700",
"sn": "xxxxxxxxxxxx",
"versão": "x.x.x"
}
}
2. Obter informações sobre a rede WWAN (celular) do dispositivo
- URL:
OBTER http://{device_IP}/rpc-api/data/wwaninfo - Método: OBTER
- Parâmetros da solicitação: Nenhum
Campos de resposta:
| Campo | Descrição | Tipo | Observações |
|---|---|---|---|
| código | Código de estado da resposta | int | Sempre 200 em caso de sucesso |
| data.enable | Com ligação móvel | booleano | true = ativado, false = desativado |
| data.status | Estado da ligação por linha telefónica | número | 0 = ligado, 1 = a inicializar, 2 = deteção do cartão SIM, 3 = PDP ativado, 4 = a marcar, 5 = pronto |
| data.ip | Endereço IP da WWAN | cadeia de caracteres | Endereço IP atribuído pela rede móvel |
| data.mask | Máscara de sub-rede | cadeia de caracteres | Máscara de sub-rede |
| data.gateway | Endereço do gateway | cadeia de caracteres | Gateway predefinido |
| data.metric | Métrica de rota | número | Valor mais baixo = prioridade mais elevada |
| data.dns | Servidor DNS | cadeia de caracteres | Endereço do resolvedor DNS |
| data.versão | Versão do firmware do módulo | cadeia de caracteres | Versão do firmware do módulo 5G/4G |
| data.imei | IMEI | cadeia de caracteres | Número IMEI do módulo |
| data.signal | Intensidade do sinal | número | 0–100, quanto maior, tanto mais forte é o sinal |
| data.ccid | ID do cartão SIM | cadeia de caracteres | ICCID do cartão SIM |
| data.operator | Operadora | cadeia de caracteres | Nome da transportadora atualmente registada |
| data.sim.maxcall | Número máximo de tentativas de rediscagem | número | Limite de tentativas em caso de falha na marcação |
| data.sim.sim0.auth | Método de autenticação APN | número | 0 = Nenhum, 1 = PAP, 2 = CHAP, 3 = PAP/CHAP |
| data.sim.sim0.addr | Endereço APN | cadeia de caracteres | Nome do ponto de acesso |
| data.sim.sim0.name | Nome de utilizador APN | cadeia de caracteres | Nome de utilizador para autenticação APN |
| data.sim.sim0.passwd | Palavra-passe APN | cadeia de caracteres | Palavra-passe de autenticação APN |
| data.sim.sim0.pinCode | Código PIN | cadeia de caracteres | Código PIN do cartão SIM |
| data.ping.enable | Sonda de rede | booleano | true = ativado, false = desativado |
| data.ping.addr0 | Anfitrião da sonda 0 | cadeia de caracteres | Endereço de destino da sonda de rede 1 |
| data.ping.addr1 | Anfitrião da sonda 1 | cadeia de caracteres | Endereço de destino da sonda de rede 2 |
| data.ping.cyc | Intervalo de sondagem | número | Intervalo em segundos |
| data.ping.num | Contagem de sondas | número | Contagem do limiar de falhas |
| data.ping.state | Estado da sonda | número | 255 = não testado, 0 = falha, 1 = sucesso |
Exemplo de resposta:
{
"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 pré-instalado
O EC700 vem com vários pacotes de software industrial pré-instalados e configurados para arranque automático. Eis como gerir cada um deles.
1. Programa de Gestão Interna (iotrouter)
Para simplificar a experiência do utilizador, a série EC700 vem equipada com o iotrouter programa de gestão que é iniciado no arranque. O programa de gestão inclui:
- Inicialização do dispositivo
- Gestão de redes
- Gestão celular
- Gestão de redes Wi-Fi
- Firewall
- Serviço de configuração do dispositivo (porta predefinida 80, configurável; ficheiro:
/usr/local/src/iotrouter/web/user-config.js) - Explorador de ficheiros (caminho predefinido:
/run/media/; configurável; ficheiro:/usr/local/src/iotrouter/web/user-config.js)
Nota: Recomenda-se manter o programa interno em execução. Se for necessário desativá-lo, terá de assumir você mesmo a gestão dos serviços acima referidos.
2. NeuronEX
O EC700 vem com o NeuronEX-Lite pré-instalado. O serviço inicia automaticamente ao arrancar o sistema e fica à escuta na porta 8085.
Para uma introdução, consulte: [Percurso de aprendizagem dos computadores industriais ARM da série EC]
Ver o estado do serviço: systemctl status neuronex
Reiniciar o serviço: systemctl restart neuronex
Parar o serviço: systemctl stop neuronex
Desativar o arranque automático: systemctl disable neuronex
3. Nó-RED
O EC700 vem com o Node-RED pré-instalado. O serviço inicia automaticamente no arranque e fica à escuta na porta 1880. Para uma introdução, consulte: [Percurso de aprendizagem dos computadores industriais ARM da série EC]
Ver o estado do serviço: systemctl status node-red
Reiniciar o serviço: systemctl restart node-red
Parar o serviço: systemctl stop node-red
Desativar o arranque automático: systemctl disable node-red
4. FUXA
Todos os produtos da série EC700 vêm com o FUXA pré-instalado. O serviço inicia automaticamente no arranque e fica à escuta na porta 1881. Para uma introdução, consulte: [Guia de Desenvolvimento Avançado para Computadores Industriais ARM da Série EC]
Ver o estado do serviço: systemctl status fuxa
Reiniciar o serviço: systemctl restart fuxa
Parar o serviço: systemctl stop fuxa
Desativar o arranque automático: systemctl disable fuxa
5. Ambiente de trabalho Xfce4
O ambiente de trabalho predefinido é o Xfce4. Este é fornecido apenas a título de demonstração. Se precisar de apresentar outros conteúdos, como uma interface de utilizador baseada em Qt, pode desenvolvê-la você mesmo.
O gestor de ecrãs é: lightdm
Ver o estado do serviço: systemctl status lightdm
Reiniciar o serviço: systemctl restart lightdm
Parar o serviço: systemctl stop lightdm
Desativar o arranque automático: systemctl disable lightdm
6. Programas personalizados do utilizador
As aplicações dos utilizadores são desenvolvidas de forma independente pelos próprios utilizadores e executadas como processos separados. No entanto, é necessário prestar especial atenção à gestão da memória e do armazenamento para evitar exceções do sistema. É possível adicionar software para que seja iniciado automaticamente pelo sistema através dos seguintes métodos:
/etc/rc.local- serviço systemd
/etc/init.dsistema
Também oferecemos serviços de desenvolvimento de software personalizado. Para mais informações, Por favor, contacte a nossa equipa de vendas.
7. Personalização do logótipo de arranque
Os utilizadores podem substituir eles próprios o logótipo de arranque do sistema.
| Ficheiro do logótipo | Palco de Exposição |
|---|---|
| logo.bmp | Exibido durante a fase U-Boot |
| logo_kernel.bmp | Exibido durante a fase de arranque do kernel |
7.1 Requisitos de formatação
A imagem do logótipo deve ser um Imagem BMP de 24 bits. A resolução da imagem não deve exceder a resolução do ecrã HDMI ligado.
7.2 Substituição do logótipo
- Ligue o dispositivo.
- Copie a sua personalização
logo.bmpelogo_kernel.bmpficheiros para oSDK_PATH/kernel-6.1diretório, substituindo os ficheiros existentes com o mesmo nome.

Nota: Os nomes dos ficheiros dos logótipos não devem ser alterados.
Conclusão
O EC700 foi concebido para o ajudar a passar rapidamente do conceito ao protótipo implementado. Entre o ambiente Linux aberto, o conjunto de software industrial pré-instalado (Node-RED, NeuronEX, FUXA) e as interfaces de hardware simples, a maior parte do trabalho de base já está feita — basta escrever a lógica da sua aplicação e ligar os seus sensores e atuadores.
Algumas coisas que vale a pena ter em conta ao começar a programar:
- Comece pela porta série de depuração. Mesmo que pretenda trabalhar através do SSH, a porta de depuração Type-C é a sua alternativa quando a rede não estiver a funcionar bem.
- Aproveite a API REST. O
/rpc-api/data/Os endpoints facilitam imenso a obtenção de informações sobre os dispositivos e o estado da rede móvel para os seus próprios painéis de controlo ou scripts de monitorização — não é necessário analisar manualmente os comandos AT. - Respeite o serviço iotrouter. Este componente gere a rede, o Wi-Fi e a rede móvel em segundo plano. Se o desativares, terás de te encarregar de reimplementar essas funções.
- Tenha em atenção o seu orçamento para armazenamento. Com 128 GB de memória interna e a possibilidade de expansão NVMe, tem espaço de sobra — mas as imagens do Docker e os pesos dos modelos de IA acumulam-se rapidamente.
Se estiver à procura das especificações completas do hardware, da tabela de compatibilidade de protocolos ou das opções de personalização OEM/ODM, consulte o Página do produto EC700. Para questões relacionadas com o acesso ao SDK, desenvolvimento personalizado ou encomendas em grande quantidade, a equipa da IOTRouter está pronta para ajudar — basta contactar-nos através do formulário de contacto disponível no site.
Agnes Wang é especialista em soluções de IoT na IOTRouter, dedicando-se principalmente a gateways de IoT industrial, computação de ponta e soluções de automação industrial.
É especialista em tecnologias de comunicação industrial, incluindo Modbus, IEC 60870-5-104, MQTT, OPC UA, integração de PLC e aplicações de monitorização remota. Colabora na elaboração de artigos técnicos e guias de aplicação sobre soluções de IoT industrial, conversão de protocolos e computação na periferia.
- Agnes Wang
- Agnes Wang
- Agnes Wang11 de setembro de 2026
- Agnes Wang10 de setembro de 2026



