Как одновременно управлять ШИМ и цифровыми контактами через Ethernet в Arduino

Я использую Controllino Maxi. Внутри находится Arduino Uno. Я пытаюсь управлять выводом PWM D0 и цифровым выводом R0 с помощью кода python. Ниже приведен код, который я загрузил на Arduino:

Код Arduino:

#include <Ethernet.h> 
#include <EthernetUdp.h> 
#include <SPI.h> 
#include <Controllino.h>

byte mac[] ={}; 
IPAddress ip(192, 168, 0, 200); 
unsigned int localPort = 5000; 
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; 
String datReq; 
int packetSize; 
EthernetUDP Udp; 

void setup() 
{
  Ethernet.begin( mac, ip); 
  Udp.begin(localPort); //Инициализировать UDP
  pinMode(CONTROLLINO_D0, OUTPUT);
  pinMode(CONTROLLINO_R0, OUTPUT);

}

void loop() {
  packetSize =Udp.parsePacket(); //Чтение размера пакета
  if(packetSize>0) 
  {
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE); //Чтение запроса данных
    String datReq(packetBuffer);
    if (datReq == "R0") 
    {
      digitalWrite(CONTROLLINO_R0, HIGH);
      delay(2000);
      digitalWrite(CONTROLLINO_R0, LOW);
    }
    else 
    {
      analogWrite(CONTROLLINO_D0, datReq.toInt());
      delay(2000);
      analogWrite(CONTROLLINO_D0, 0);
    }
  }
 }

В приведенном выше коде, если я получаю R0 через Ethernet, я включаю/отключаю контакт R0, в противном случае, какой бы ШИМ я ни получал, я устанавливаю его с помощью аналоговая запись. Ниже приведен мой код python:

from socket import *
import time

address = ('192.168.0.200', 5000)  # define server IP and port ((0x12, 0x02, 0x00, 0x00, 0xEA, 0x03))
client_socket = socket(AF_INET, SOCK_DGRAM)  # Set up the Socket
client_socket.settimeout(1)

data = "R0".encode("utf-8")  
client_socket.sendto(data, address)  
time.sleep(5)

data = ("{}".format(200)).encode("utf-8")  
client_socket.sendto(data, address)  
time.sleep(5)

data = ("{}".format("R0")).encode("utf-8")  
client_socket.sendto(data, address)  

В приведенном выше коде я сначала отправляю R0 для включения/выключения R0, затем отправляю 200 для PWM, а затем снова отправляю R0 для включения/выключения R0. При тестировании я вижу, что R0 становится высоким и низким, затем я вижу 200 на ШИМ, но затем снова R0 должен быть высоким/низким, но это остается низким. Если я повторно запускаю код Python, R0 не работает, и работает только PWM. Если я выключу плату и снова включу питание, то R0 сработает только в первый раз и не сработает во второй раз.

Я немного запутался на этом этапе. Есть ли ошибка в моем коде Arduino, так как я не очень разбираюсь в этом. Есть ли способ отладить его? Пожалуйста помоги. Спасибо

, 👍0


1 ответ


Лучший ответ:

2

Скетч Arduino сохраняет полученный пакет UDP в массиве char с именем packetBuffer, а затем преобразовать этот массив в объект String вот так:

String datReq(packetBuffer);

Проблема в том, что этот конструктор String ожидает завершение NUL массив, и у вас нет гарантии, что этот массив завершается NUL.

Ну, на самом деле у вас есть эта гарантия, но только в начале: как программа запустится, массив будет заполнен нулями по C процедура инициализации. Вот почему первый запрос правильный обработанный. Второй запрос отправляет пакет большего размера, чем первый, поэтому массив по-прежнему завершается NUL. Однако по третьему требованию за принятыми байтами сразу же следуют остатки предыдущего запрос. В данном случае это цифра '0'.

Простое решение – убедиться, что буфер всегда прекращено. Начните с расширения на один байт:

char packetBuffer[UDP_TX_PACKET_MAX_SIZE + 1]; // +1 для '\0'

Затем всякий раз, когда вы получаете пакет, добавляйте завершающий символ NUL:

Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE); //Чтение запроса данных
packetBuffer[packetSize] = '\0'; // корректно завершить работу буфера
,