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

asked Nov 9, 2022 at 13:19

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
answered Nov 9, 2022 at 13:43
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.