Problem with using Arduino and python together

I am having problem with using Arduino and python together I don't know why but Arduino is not responding to the python command and is sending back gibberish data
here is the Arduino script:

 String inbyte;
 void setup() {
  // put your setup code here, to run once:
 Serial.begin(9600);
 pinMode(LED_BUILTIN,OUTPUT); 
 }
 
 void loop() {
  // put your main code here, to run repeatedly:
 if(Serial.available()>0){
  Serial.readStringUntil('\n');
   if(inbyte == "on"){
   digitalWrite(LED_BUILTIN,HIGH);
  Serial.println("led on");
   }
   if(inbyte == "off"){
   digitalWrite(LED_BUILTIN,HIGH);
   Serial.println("led off");
   }
 }
 }

and this is the python code

import serial
import time
com = serial.Serial('/dev/tty.usbmodem1101', 9600)
while True:
    i = input('cmd byte:').strip()
    if i == 'done':
        print('program ended')
        break
    com.write(i.encode())
    time.sleep(0.5)
    print(com.readline().decode('ascii'))
com.close()

any help would be appreciated :slightly_smiling_face:

You read in the string but you do not assign the read-in-bytes to a variable
You just read in and throw it away.

best regards Stefan

but then python sends the command ending with '\n' and if I don't remove it the if statement thinks that there is no on command there is only on\n command
so how do I do that and If possible could you send the revised version of the Arduino code.
regards Aujas

my opinion about this forum:
it is here to help. It is not there to write code for others.

Make an own attempt. And as soon as you have made an own attempt to code it I will explain in detail what is right and what has to be changed in your attempt.

I'm 101% sure that you know how assigning a variable is coded.

best regards Stefan

The question is:

where is the line of code where the variable "inbyte" gets its value from?
There is no assigning of the received value to this variable.

And as soon as you assign the received bytes to this variable everything works.

best regards Stefan

Hey there I did some tries and now it turns on when python send 'on' command but doesn't turn off when python says it to

Your program does what you have coded
"HIGH" is for on but where is the "LOW" for led off?
best regards Stefan

oops :sweat_smile: thanks buddy

That's one of the purposes of this forum.
Showing the solution

umm there is a problem...

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
pinMode(LED_BUILTIN,OUTPUT); 
}

void loop() {
  // put your main code here, to run repeatedly:
if(Serial.available()>0){
  if(Serial.readString() == "on"){
  digitalWrite(LED_BUILTIN,HIGH);
  Serial.println("led on");
  }
  if(Serial.readString() == "off"){
  digitalWrite(LED_BUILTIN,LOW);
  Serial.println("led off");
  }
  else{
    Serial.println("sorry but you coded it wrong");
  }
}
}

if I type off in python it says sorry but you coded it wrong (the else statement) why could you tell?
regards Aujas

Your code does exactly what you have coded
Code always does

exactly

what you have coded
If it is something different than yozu expected you don't understand your own code yet.

You have one if without an else

if(Serial.readString() == "on"){
  digitalWrite(LED_BUILTIN,HIGH);
  Serial.println("led on");
  }

and one if with an else

if(Serial.readString() == "off"){
  digitalWrite(LED_BUILTIN,LOW);
  Serial.println("led off");
  }
  else{
    Serial.println("sorry but you coded it wrong");
  }

whenever the condition

if(Serial.readString() == "off")

is not true the else is executed.

The reason to use a microcontroller with RAM is to define multiple variables and to use the variables
This was your original code at the beginning

String inbyte;
 void setup() {
  // put your setup code here, to run once:
 Serial.begin(9600);
 pinMode(LED_BUILTIN,OUTPUT); 
 }
 
 void loop() {
  // put your main code here, to run repeatedly:
 if(Serial.available()>0){
  Serial.readStringUntil('\n'); //<<<= reading in bytes but the bytes get NOT assigned. you just throw them away

simply assign the read-in-bytes to your variable

inbyte = Serial.readStringUntil('\n');

and everything works

String inbyte;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  if (Serial.available() > 0) {
    inbyte = Serial.readStringUntil('\n');  // <<<===== assign the read-in-bytes to the variable 
    
    if (inbyte == "on") {
      digitalWrite(LED_BUILTIN, HIGH);
      Serial.println("led on");
    }
    if (inbyte == "off") {
      digitalWrite(LED_BUILTIN, LOW);
      Serial.println("led off");
    }
  }
}

Serial.readStringUntil('\n'); //<<<= reading in bytes but the bytes get NOT assigned. you just
inbyte = Serial.readStringUntil('\n'); // <<<===== assign the read-in-bytes to the variable

best regards Stefan

hey thanks a lot dude !! it worked .

take a look at this single line of code

    dbg("1:",inbyte);

This single line of code does three things:

  1. print a fixed text
  2. print the name of the variable
  3. print the value of the variable

In this example dbg("1:",inbyte);

  1. the fixed text is: "1:"
  2. the variable-name is "inbyte"
  3. the value of the variable: will be what you have sent over the serial connecttion

some more examples

let's say a variable with name "myInteger"

int myInteger;

myInteger  = -24;

So the command

dbg("blabla", myInteger);

will print to the serial monitor

"blabla" myInteger=-24

let's say a variable with name "OutsideTemperature"

float OutsideTemperature;

OutsideTemperature= readTemperature();

So the command

dbg("HuhU!", OutsideTemperature);

will print to the serial monitor

"HuhU!" OutsideTemperature=5.32

This gives you insight what your code is really doing and what values variables really have

This makes it very easy to analyse code.

This is done by a "thing" called macro.
macros work on a different level than code. You can imagine a macro as a co-worker typing on the keyboard modifying your sourcecode in a programmed way

If take a first look at the macro you will be confused.
Well you have seen example how to use it. (see above)
So using the maro is easy. Understanding needs some time.

The macro that does the above looks like this

#define dbg(myFixedText, variableName) \
  Serial.print( F(#myFixedText " "  #variableName"=") ); \
  Serial.println(variableName);

Here is your demo-code with a second macro that prints only in intervals.
This makes sense if you have a fast running loop where you don't need hundreds of prints every second but only one print per second

Here is a code-version of your code that demonstrates this

use this example code with the serial monitor of the arduino-IDE!

Your python-code is somehow lazy in printing the send back characters.
This is caused by the logic of your python-code not by the computerspeed itslef.

// start of macros dbg and dbgi
#define dbg(myFixedText, variableName) \
  Serial.print( F(#myFixedText " "  #variableName"=") ); \
  Serial.println(variableName);
// usage: dbg("1:my fixed text",myVariable);
// myVariable can be any variable or expression that is defined in scope

#define dbgi(myFixedText, variableName,timeInterval) \
  do { \
    static unsigned long intervalStartTime; \
    if ( millis() - intervalStartTime >= timeInterval ){ \
      intervalStartTime = millis(); \
      Serial.print( F(#myFixedText " "  #variableName"=") ); \
      Serial.println(variableName); \
    } \
  } while (false);
// usage: dbgi("2:my fixed text",myVariable,1000);
// myVariable can be any variable or expression that is defined in scope
// third parameter is the time in milliseconds that must pass by until the next time a 
// Serial.print is executed
// end of macros dbg and dbgi

String inbyte;

void setup() {
  Serial.begin(9600);
  Serial.println( F("Setup-Start") );  
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {

  dbgi("top of loop",digitalRead(LED_BUILTIN),3000); // print only once every 3000 milliseconds

  if (Serial.available() > 0) {
    inbyte = Serial.readStringUntil('\n');  // <<<===== assign the read-in-bytes to the variable 
    dbg("1:",inbyte);
    
    if (inbyte == "on") {
      digitalWrite(LED_BUILTIN, HIGH);
      Serial.println("led on");
    }
    if (inbyte == "off") {
      digitalWrite(LED_BUILTIN, LOW);
      Serial.println("led off");
    }
  }
}

best regards Stefan

thanks dude

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.