Guia de Desenvolvimento do EC700: Introdução ao PC industrial para computação de ponta com IA

Este 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:

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
    • 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.d sistema

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

  1. Ligue o dispositivo.
  2. Copie a sua personalização logo.bmp e logo_kernel.bmp ficheiros para o SDK_PATH/kernel-6.1 diretório, substituindo os ficheiros existentes com o mesmo nome.

Guia de Desenvolvimento do EC700: Introdução ao PC industrial para computação de ponta com IA

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.

 

Sobre mim
db6893fd1d3e314ac461fa240068dc06?s=150&d=mp&r=g
Especialista em Soluções de IoT ~ Web ~  Mais publicações

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.

↑