0

I am using Controllino Maxi. It has an Arduino Uno inside it. I am trying to control the PWM pin D0 and digital pin R0 via python code. Below is the code I have upload on arduino:

Arduino Code:

#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); //Initialize Udp
  pinMode(CONTROLLINO_D0, OUTPUT);
  pinMode(CONTROLLINO_R0, OUTPUT);

}

void loop() {
  packetSize =Udp.parsePacket(); //Reads the packet size
  if(packetSize>0) 
  {
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE); //Read the data request
    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);
    }
  }
 }

In above code, if I receive R0 over ethernet, then I am turning on/off R0 pin, else whatever PWM I am receiving, I am setting it using analogWrite. Below is my python code:

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)  

In above code, I am first sending R0 to turn on/off R0 and then sending 200 for PWM and then again sending R0 to turn on/off R0. When tested I can see R0 getting high and low, then I can see 200 on PWM but then again R0 should be high/low but it stays low. If I re run the python code, R0 doesnt work and only PWM works. If I power off the board and power it again, then R0 works only for first time and it didnt work in second time.

I am a bit confused at this stage. Is there any bug in my arduino code as I am not very experienced in it. Is there any way to debug it? Please help. THanks

1 Answer 1

2

You Arduino sketch is storing the received UDP packet in a char array named packetBuffer, then converting this array to a String object like this:

String datReq(packetBuffer);

The problem is that this String constructor expects a NUL-terminated array, and you have no guarantee that this array is NUL-terminated.

Well, actually you have this guarantee, but only at the beginning: as the program starts, the array will be filled with zeros by the C initialization routine. This is why the first request is correctly processed. The second request sends a packet larger than the first one, so the array is still NUL-terminated. On the third request, however, the received bytes are immediately followed by the leftovers of the previous request. In this case it is the digit '0'.

The simple solution is to ensure that the buffer is always properly terminated. Start by making it wider by one byte:

char packetBuffer[UDP_TX_PACKET_MAX_SIZE + 1]; // +1 for the '\0'

Then, whenever you receive a packet, add the terminating NUL character:

Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE); //Read the data request
packetBuffer[packetSize] = '\0'; // properly terminate the buffer
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.