2

I'm trying to make Arduino trigger a relay if the char "s" is read on serial port. That char "s" is sent by python based on an image read from screen.

My problem is that arduino seems not able to read from serial port as it never performs the if condition. My guess is that there is some kind of deadlock between the two (that's why I put ardu.close() in the function foo)

This is my arduino code:

char serial;
#define RELAY1  7                        
void setup()

{    


Serial.begin(9600);
  pinMode(RELAY1, OUTPUT);       

}

  void loop()

{


if(Serial.available() > 0){
    serial = Serial.read();
    //Serial.print(serial);
    if(serial=='s'){
      digitalWrite(RELAY1,0);           
   Serial.println("Light ON");
   delay(2000);                                      

   digitalWrite(RELAY1,1);          
   Serial.println("Light OFF");
   delay(2000);
      }
      } 
}

This is my python code:

import time
import serial
#from serial import serial
import cv2
import mss
import numpy
import pytesseract

def foo():
    print("sent")
    ardu= serial.Serial('COM6',9600, timeout=.1)
    time.sleep(1)
    ardu.write('s'.encode())
    time.sleep(1)
    ardu.close()


foo()
7
  • I assume you are actually seeing the "sent" message from the Python code? You might need a sleep() after the write as well as before; that immediate close you're currently doing could potentially shut down the serial port before the character has been fully sent. Commented Oct 6, 2018 at 22:12
  • Please edit this down to an mcve. Since this is about communicating to Arduino, you don't need all of that with images, mss, pytesseract, etc. In making the simplified code, you may also figure this out yourself along the way. Commented Oct 6, 2018 at 22:14
  • Thank you tom10, you are right! I edited it. Commented Oct 6, 2018 at 23:05
  • @jasonharper I've tried to add time.sleep(1) before and after the write but nothing has changed. Commented Oct 6, 2018 at 23:13
  • If you want to control your Arduino without having to write an Arduino program too, you can use PyFirmata: youtube.com/watch?v=RS35q6ksU6w Commented Oct 6, 2018 at 23:19

1 Answer 1

2

To communicate with the Arduino board from a Windows machine, you have to install PySerial. See the instructions here for installing PySerial on your machine: PySerial website

And, make sure that you have installed the correct serial driver for your board. This should be installed with your board software. But, in case you need to do it manually, here are two links that may be helpful, Sparkfun driver instructions and Arduino driver instructions

Then, make sure that you are using the correct com port. Run your arduino IDE, upload your program to the arduino, and then under the Tool menu (in the IDE), set the com port and run the serial monitor. Then, in the serial monitor, enter an 's' and verify that you see the light on, light off messages.

Here are your arduino and python codes, stripped to the minimum set of instructions to demonstrate your example, plus a println() statement (in the arduino code) to echo the received characters in hex. That debugging statement will help you sort out line feeds and so forth as you develop your code.

The codes as listed here, work on my board and Linux machine after changing the pin number for the relay, and the device name for the port. The close() is commented-out only to show you that it works without that line.

On the arduino:

#include <stdlib.h>

char serial;
#define RELAY1  7                       
void setup()
{    
  Serial.begin(9600);
  pinMode(RELAY1, OUTPUT);       
}

void loop()
{
  if(Serial.available() > 0)
  {
      serial = Serial.read();
      Serial.println( serial, HEX);
      if (serial=='s')
      {
        digitalWrite(RELAY1,0);           
        Serial.println("Light ON");
        delay(2000);                                      
        digitalWrite(RELAY1,1);          
        Serial.println("Light OFF");
        delay(2000);
      }
   } 
}

The python code:

import time
import serial

def foo():
    print("sent")
    ardu= serial.Serial('/dev/ttyACM0',9600, timeout=.1)
    time.sleep(1)
    ardu.write('s'.encode())
    time.sleep(1)
    #ardu.close()


foo()
Sign up to request clarification or add additional context in comments.

10 Comments

Thank you @DrM for your answer. I have tried to open the serial monitor to see if python was actually sending the char "s" but if I open the serial monitor before sending with python the char python prints an error that says "Error 5. Access Denied". If I send the char "s" before opening the serial monitor the serial monitor won't start stating "Port already in use". That is why I guessed there was some kind of lock to put in order to write/read from serial. I already have pyserial because I was having problems with serial.
The com port can be opened by only one program at a time. --- That is why you see the error messages, 'access denied' and 'port already in use'.
Start the serial monitor, do not start your python program. Type the 's' into the single line text entry 'widget' at the top of the serial monitor, and then click the 'send' button at the right of the entry widget, or use the 'enter' key on your keyboard.
I'm here now, and ready to help you. So please try this and let me know what happens.
Thank you! If I send s with the serial monitor( without python) it works
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.