Error in arduino communication with COM - python

Arduino code
#include <TFT.h>
#include <SPI.h>
#define cs 10
#define dc 9
#define rst 8
TFT TFTscreen = TFT(cs, dc, rst);
int led = 13;
void setup() {
TFTscreen.begin();
Serial.begin(9600);
pinMode(led, OUTPUT);
}
void loop() {
TFTscreen.background(0, 0, 0);
TFTscreen.setTextSize(1);
if (Serial.available() > 0) {
digitalWrite(led, HIGH);
TFTscreen.text(Serial.read(), 0, 0);
}
}
Python code
import os
import sys
import serial
import datetime
ser = serial.Serial('COM4', 9600)
print(ser.name)
print(datetime.datetime.now())
date_string = str(datetime.datetime.now())
date_bytes = date_string.encode('ascii')
ser.write(date_bytes)
print('OK')
ser.close
Python is working normal, but Arduino give me this error invalid conversion from 'int' to 'const char*' [-fpermissive], I think problem with Type of Data, but I began learn this language yesterday.

The problem is here I think:
TFTscreen.text(Serial.read(), 0, 0);
You call the "read" function which returns an integer. The "text" function of your screen wants a char pointer instead as the first parameter, and you can't cast an int to char* like said in the error "invalid conversion from 'int' to 'const char*"
You can look up all the parameter and return types in the arduino documentation:
https://www.arduino.cc/en/Serial/Read

maybe, on your python add a '\0' before sending the string to the serial, this will serve as the end of received string. I can not remember if python is sending this by default but you can explicitly just send this.
on the arduino, fetch the received data and fill a character array (maybe use a counter or do pointer aritchmetic, be careful of going past the array's declared maximum size), and then wait for the '\0'. once it gets the \0, append it as well to the char array, and do a TFT display. then repeat the process again, reset the counter then wait for the incoming byte stream.
I haven't used that TFT library but one of the problems that I anticipate in your implementation is that it will not display any words because you will keep on writing every character to 0,0.

Related

Arduino to Raspberry Pi Pyserial Communication not working on Python

I have a Python script that takes in input from a camera. It then gets the position of an object in the image and sends it to the Arduino via pyserial and usb with the following format.
"Xpos-XYPos-Y" demo: 90X90Y would move the servos I have connected to 90 degrees.
What should happen when i run bellow should be that it moves the motors.
import serial
ser = serial.Serial('/dev/ttyACM1', 9600, timeout=1)
ser.flush()
ser.write(bytes("90X90Y", encoding='utf-8'))
But what really happens... Nothing?
So I thought okay, it might just be that my code is wrong so I tried many different variations.
I would list them but then it would take way too long to read. Basically, I changed the encoding and how I turn it into bytes.
I know the problem isn't my hardware (or at least I think) because I can download the Arduino IDE
onto the pi and send serial info through there. And it works!
Here is my Arduino code:
#include <Servo.h>
// Define Objects
Servo X;
Servo Y;
// Create varibles
String learndata;
String receiveX;
String receiveY;
int moveX;
int moveY;
// Straight forward
int defX = 95;
int defY = 5;
void setup(){
Serial.begin(9600);
//Attatch servos
X.attach(6);
Y.attach(7);
}
void loop(){
if (Serial.available() > 0){
// Parse servo input
receiveX = Serial.readStringUntil('X');
receiveY = Serial.readStringUntil('Y');
moveX = receiveX.toInt();
moveY = receiveY.toInt();
X.write(moveX);
Y.write(moveY);
}//if (Serial.available() > 0){
}//void loop(){
I also tried fully updating the raspberry pi to no avail.
Any help and what I should do? Are there any alternatives?

Unable to send byte from Python serial.write() to Arduino

I wrote a python script that sends and receive data to and from an Arduino. I can receive data without problems, but when I send data it seems like the Arduino is receiving only garbage.
The Arduino is connected to a linux pc via USB and the pc is running Python 3.8.
Since the original code contains a lot of unrelated stuff and may be distracting, I prepared the simplest possible sketch to demontrate the problem:
Python code:
#! /usr/bin/env python
import serial
import time
if __name__ == '__main__':
ser = serial.Serial("/dev/ttyACM0", 9600, timeout=0)
time.sleep(5) # Wait for Arduino to reset and init serial
ser.write(67)
Arduino sketch
const byte LED_PIN = 13;
void setup() {
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
}
void loop() {
if (Serial.available() > 0) {
byte b = Serial.read();
if (b == 67) {
digitalWrite(LED_PIN, HIGH);
delay(500);
digitalWrite(LED_PIN, LOW);
}
}
}
This code flashes the onboard LED when receives a byte with value 67 (uppercase C). This works with the Arduino Serial Monitor, but not when running the Python script.
I feel like my problem may be related to this question, but in that case the focus was on the user not considering the case of an empty serial input buffer, while I believe the problem is actually in the sent data. This is why I decided to leave out the receiving part and simplify the example using only the onboard led.
Update
I made it work changing the last line in the python script to:
ser.write(bytes([67]))
(note the [] added around the integer value).
Anyone can explain why this syntax produces the correct result? It seems like I'm passing a single entry array to the function bytes().
Pardon my poor skills in Pyton, I know the question is probably basic.
It's really simple; the methods you tried that worked all conform to the specification for the pyserial library.
Per the Pyserial documentation:
write(data)
Parameters: data ā€“ Data to send.
Returns: Number of bytes written.
Return type: int
Raises: SerialTimeoutException ā€“ In case a write timeout is configured for the port and the time is exceeded.
Write the bytes data to the port. This should be of type bytes (or compatible such as bytearray or memoryview). Unicode strings must be encoded (e.g. 'hello'.encode('utf-8').
This is why the b'C style worked as well as the bytes call.
Attribution: Pyserial Page

Python Serial Communication Arduino Led Controlling Problems

I am trying to control a total of 6 LEDS with python. I was using pyserial to send arduino some data but I have encountered several problems with it.
The first problem I have encountered was:
According to the code I have written on arduino, the LEDS should blink for 1 second for several amount of times a specific data received. (This is later explained below.) However, the LEDS stay on the number of seconds they should blink. Meaning if the LEDS are supposed to blink for 10 times. The LEDS stay on for 10 seconds and turn off.
The second problem was:
The if conditions I have put in the code was not in order. As you can see in the arduino code, the if conditions are in order. However, this is what happens when I run the code.
The first LED lights up for 10 seconds, the second one lights up for 10 seconds as well. And later on the fifth one lights up.
To explain a little more of the code:
I am storing lists inside a list inside of python. There is a for loop that sends each list with a delay of 1 second.
The list has 6 elements.( This is for later experimentation.) However, in this work only the first two of elements of each list matter.
In order to negate the auto reset on arduino, I put 10 microfarad capacitor between the ground and reset. After that I run the python code to send the data.
I think I have explained the situation with details, however I am open to suggestions and will answer questions on the comments.
The Python Code:
import time
import serial
incomingByte2=[[1,20,200,300,400,500],[2,30,24,63,200],[3,5,400,500,100,200],[4,10,1,1,1,1],[5,10,1,1,1,1],[6,10,1,1,1,1]]
uzunluk= len(incomingByte2)
def close():
# arduino=serial.Serial("COM4",9600)
arduino = serial.Serial(
port='COM3',\
baudrate=115200,\
parity=serial.PARITY_NONE,\
stopbits=serial.STOPBITS_ONE,\
bytesize=serial.EIGHTBITS,\
timeout=0)
print("connected to: " + arduino.portstr)
for i in range(0,uzunluk):
arduino.write(str.encode(str(incomingByte2[i])))
time.sleep(1)
The Arduino Code:
int ledPins[] = {2,3,4,5,6,7,8,9};
int incomingdata[6];
int ilkled,ikinciled,ucunculed,dordunculed,besinciled,altinciled;
void setup() {
// put your setup code here, to run once:
int index;
Serial.begin(115200);
for(index = 0; index <= 7; index++)
{
pinMode(ledPins[index],OUTPUT);
}
}
void loop() {
// put your main code here, to run repeatedly:
if(Serial.available()){
for (int a=0; a < 6; a++) {
incomingdata[a] = Serial.parseInt();
delay(100);
ilkled=incomingdata[0];
ikinciled=incomingdata[1];
ucunculed=incomingdata[2];
dordunculed=incomingdata[3];
besinciled=incomingdata[4];
altinciled=incomingdata[5];
}
}
if (ilkled==1){
for (int x=0;x<ikinciled;x++){
digitalWrite(ledPins[0],HIGH);
delay(1000);
digitalWrite(ledPins[0],LOW);
}
}
if (ilkled==2){
for (int x=0;x<ikinciled;x++){
digitalWrite(ledPins[1],HIGH);
delay(1000);
digitalWrite(ledPins[1],LOW);
}
}
if (ilkled==3){
for (int x=0;x<ikinciled;x++){
digitalWrite(ledPins[2],HIGH);
delay(1000);
digitalWrite(ledPins[2],LOW);
}
}
if (ilkled==4){
for (int x=0;x<ikinciled;x++){
digitalWrite(ledPins[3],HIGH);
delay(1000);
digitalWrite(ledPins[3],LOW);
}
}
if (ilkled==5){
for (int x=0;x<ikinciled;x++){
digitalWrite(ledPins[4],HIGH);
delay(1000);
digitalWrite(ledPins[4],LOW);
}
}
if (ilkled==6){
for (int x=0;x<ikinciled;x++){
digitalWrite(ledPins[5],HIGH);
delay(1000);
digitalWrite(ledPins[5],LOW);
}
}
}
I think your read loop is broken. It should close after delay(100), no?
for (int a=0; a < 6; a++) {
incomingdata[a] = Serial.parseInt();
delay(100);
}
Personally I would not string encode the data in Python. Send it as raw bytes, then read it as raw bytes into your int array.
Serial.readBytes( incomingData, 6 ); // assumes 8 bit ints.
That would do away with the loop completely.
Your LED staying on instead of flashing because you missed the line I added below.
for (int x=0;x<ikinciled;x++){
digitalWrite(ledPins[5],HIGH);
delay(1000);
digitalWrite(ledPins[5],LOW);
delay(1000); // <<<< Hold the LOW time
}
Otherwise it will be set LOW for only a few microseconds.
You may also run into synchronous issues with your Serial read versus how much time you spend in "delay()" during the LED flashing. Your python looks like it's sleeping only for 1 second, but your code responding to that will take many seconds as it delays in delay().
The Serial buffer will overflow and data will be lost/overwritten and when you call your next "parseInt" or "readBytes" there is no guarantee where the next bit of data in the buffer starts. Highly likely not at the next block of 6 ints.
You could send the data less often or send it based on how long the flashing will take. Alternatively you could implement an interrupt system to flash the LEDs... and the solutions get more complex from there up.
Welcome to the world of low level communications protocols.
PS, get rid of these
if (ilkled==6){
Just use it directly.
digitalWrite(ledPins[ilkled-1],HIGH);

Difference between SCmd.readSerial() and Serial.read()

Currently I'm trying to Send information from python to Arduino through the serial port.
I manage this using only one letter Serial.read() 'P' and executing an action on my Arduino with the following code.
Arduino code:
#define arduinoLED 12 // Arduino LED on board
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(arduinoLED, OUTPUT); // Configure the onboard LED for output
digitalWrite(arduinoLED, LOW); // default to LED off
}
void loop() {
// put your main code here, to run repeatedly:
//delay (20000);
//char comein=Serial.read();
//Serial.println(comein);
char *arg = "hello";
if (Serial.read()== 'P'){
digitalWrite(arduinoLED, HIGH);
delay(5000);
}
else {
digitalWrite(arduinoLED, LOW);
Serial.println("Hello World");
}
}
Python code:
ser.open()
ser.is_open
my_string='P'
my_string_as_bytes=str.encode(my_string)
print(my_string_as_bytes)
ser.write(my_string_as_bytes)
This works well and turn my LED on but how could I manage more then one letter for the command for example 'P1 2018' for the led to turn on?
But my real problem is that I try to do exactly the same thing, using the same Python code, but using SCmd.readSerial() to read the information in Arduino such as the following:
Arduino code:
#include <SerialCommand.h>
#define arduinoLED 12 // Arduino LED on board
SerialCommand SCmd; // The demo SerialCommand object
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(arduinoLED, OUTPUT); // Configure the onboard LED for output
digitalWrite(arduinoLED, LOW); // default to LED off
SCmd.addCommand("P1", process_command1); // Converts two arguments to integers and echos them back
SCmd.addCommand("P", relay1_on); // Turns Relay1 on
SCmd.addDefaultHandler(unrecognized); // Handler for command that isn't matched (says "What?")
Serial.println("Ready");
}
void loop() {
// put your main code here, to run repeatedly:
SCmd.readSerial(); // We don't do much, just process serial commands
}
void relay1_on()
{
digitalWrite(12, HIGH);
Serial.println(3000);
delay(3000);
digitalWrite(12, LOW);
}
void process_command1()
{
int aNumber = 5;
char *arg = "hello";
Serial.println("We're in process_command");
arg = SCmd.next();
int OhmPosition = atoi(arg); //will return only numbers
arg = SCmd.next();
int relay = atoi(arg); //will return only numbers
arg = SCmd.next();
int opentime = atoi(arg); //will return only numbers
Serial.println(OhmPosition);
Serial.println(relay);
Serial.println(opentime);
}
As you can see, their is Serial command, responding to 'P' which is the same example as above but it doesn't work for some reason and don't understand why. Any idea?
And the second Serial command is 'P1' which is where I would like to get at the end, so I could send from Python something like:
Python code:
my_string6 = 'P1'+str(actions_time_[0][0] )+' '+str(actions_time_[0][1])+' '+str(actions_time_[0][2]))
my_string_as_bytes=str.encode(my_string6)
print(my_string_as_bytes)
ser.write(my_string_as_bytes)
output looks like this=> b'P1 150.0 5.0 2000.0 '
To enable me to start the P1 command and send values, to be saved in OhmPosition, Relay, Time which will be separated by a space, as the goal is to pilot a small electrical automate.
I would be very please to have your support on theses couples of point related to each other.
How can your program tell the difference between receiving the "P1" command and receiving the "P" command followed by some random "1"
You code seems to rely on a library that isn't a standard part of the Arduino install. You should provide a link to where you got the SerialCommand class.

Random character at the beginning of serial.readline() in python and arduino

I get random characters when I perform a serial.readline(), sometimes it is other umbers and sometimes it is whole messages. The output should be "1,2" or "2,2"
Here are a couple of screenshots of the output of serial.readline().
I have tried to put a delay at before serial.readline() but it did not make a difference.
There is usually a strange character at the beginning:
I have also received strange messages:
There is a problem later on in the program that causes the program to hand because sometimes I just receive a blank line.
Is there a way to get consistent output from serial?
Here is the arduino code:
void setup() {
// initialize the LED pin as an output:
pinMode(ledPin, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
Serial.begin(9600);
}
void loop(){
// read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);
// check if the pushbutton is pressed.
// if it is, the buttonState is HIGH:
if (buttonState == HIGH) {
// turn LED on:
digitalWrite(ledPin, HIGH);
Serial.println("1,2");
}
else {
// turn LED off:
digitalWrite(ledPin, LOW);
Serial.println("2,2");
}
}
And here is the python code:
ser = serial.Serial('/dev/ttyUSB0', 9600)
line=ser.readline()
coord= line.strip()
print coord
EDIT:
I tried putting ser.flushInput() after the ser.open() and I get the same output.
Have you flushed the serial buffer
ser.flushInput()
I've been having the same issue when interfacing between pyserial and Arduino. This may be an old post, but in case someone else is having the same trouble, I remedied my problem by inserting:
ser.flushInput()
...right before my ser.readline() call.
How to Read serial data from an Arduino in Linux
Nothing fancy here. Iā€™m getting the current port configuration, setting the input/output speed to 9600 baud, setting the data expectations to be 8 bits per word, with no parity bit and no stop bit, setting canonical mode, and then committing those changes back to the serial port.
If I am not mistaken you have to change the mentioned settings when connecting through serial port.
You do not mention it, but I guess you are using the pySerial library. Regardless you can use it with the correct settings to connect through serial. The constructor of the API allows all the parameters which are noted below:
Pyserial Library
I have not tested this approach as I have had a similar problem in C not Python.
What happens if you break it down to something simpler?
On the Arduino:
void setup()
{
Serial.begin(9600);
}
int i = 0;
void loop()
{
delay(1000);
Serial.print("Hello World ");
Serial.println(i);
i++;
}
And in the Python REPL...
import serial
ser = serial.Serial('/dev/ttyUSB0', 9600)
while(1):
ser.readline()
The first behavior you should observe is that when you initiate the serial connection, the Arduino reboots. This takes a few seconds.
The second behavior you should observe is that (if you're typing this in the REPL slowly) when the while(1) loop begins, you get all of the serial data that had accumulated since you initiated the serial connection. It takes me a few seconds to type all that out, so when I hit Enter after ser.readline() I see:
'Hello World 1\r\n'
'Hello World 2\r\n'
'Hello World 3\r\n'
I only mention this to make sure you're familiar with two things that burned me a bit the last time I messed with serial communication to an Arduino: it needs time to reboot after connecting, and the serial data buffers. readline() will only give you one line in the buffer - not everything that's in the buffer.
Is it possible you're trying to sent/receive data before it's done rebooting? What about button bounce - could a dozen high/low state detections be messing something up?

Categories