I'm trying to send a '1' or a '0' to my Arduino in Python using pySerial so that from my Arduino I can read whatever the Python program sends and then turn a relay on and off depending on what it reads from Python.
Here is the Python code:
import cv2
import imutils
import threading
import time
import serial
Arduino = serial.Serial("COM7")
Arduino.baudrate = 9600
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
_, start_frame = cap.read()
start_frame = imutils.resize(start_frame, width=500)
start_frame = cv2.cvtColor(start_frame, cv2.COLOR_BGR2GRAY)
start_frame = cv2.GaussianBlur(start_frame, (21, 21), 0)
alarm = False
alarmMode = False
alarmCounter = 0
def beep_alarm():
global alarm
for i in range(5):
if not alarmMode:
break
print("HE MOVIN HE MOVIN")
Arduino.write(str.encode("1"))
alarm = False
Arduino.write(str.encode("0"))
while True:
_, frame = cap.read()
frame = imutils.resize(frame, width=500)
if alarmMode:
frameBW = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
frameBW = cv2.GaussianBlur(frameBW, (5, 5), 0)
difference = cv2.absdiff(frameBW, start_frame)
threshhold = cv2.threshold(difference, 25, 255, cv2.THRESH_BINARY)[1]
start_frame = frameBW
if threshhold.sum() > 300:
alarmCounter += 1
else:
if alarmCounter > 0:
alarmCounter -= 1
cv2.imshow("Cam", threshhold)
else:
cv2.imshow("Cam", frame)
if alarmCounter > 20:
if not alarm:
alarm = True
threading.Thread(target=beep_alarm).start()
keypress = cv2.waitKey(30)
if keypress == ord("t"):
alarmMode = not alarmMode
alarmCounter = 0
if keypress == ord("q"):
alarmMode = False
break
cap.release()
cv2.destroyAllWindows()
It's basically a movement detection program. If it detects me moving it should send a '1' to the Arduino where it then turns on a relay.
Here is the arduino code:
int relay = 11;
bool moving = false;
void setup() {
Serial.begin(9600);
Serial.setTimeout(1);
pinMode(relay,OUTPUT);
digitalWrite(relay, LOW);
}
void loop() {
while (Serial.available()) {
if (Serial.read() > 0) {
while (!Serial.available()) {
if (moving == false) {
digitalWrite(relay, LOW);
delay(100);
moving = true;
} else {
digitalWrite(relay, HIGH);
delay(100);
moving = false;
}
}
}
digitalWrite(relay,LOW);
delay(100);
}
}
-
are you able to send data successfully using serial monitor?jsotola– jsotola2024年05月28日 20:22:54 +00:00Commented May 28, 2024 at 20:22
1 Answer 1
You didn't specify, what the problem actually is, but I already see an error, that is probably the problem here.
You are sending the string "0" or the string "1" from python. This being a string - in contrast to a number in some binary format - means, that it is encoded as ASCII text. Have a look at an ASCII table, for example here. You will find the symbol/character "0" to have a decimal value (DEC) of 48
. "1" is decimal 49
.
On the Arduino side you have Serial.read() > 0
. Serial.read()
returns an integer, so a decimal number (or more specific a binary representation of it). So you got either 48 > 0
or 49 > 0
, which is always true. Keep in mind the difference between ASCII encoding and binary integer encoding.
You can replace the above with
if(Serial.read() == '1'){
This tests, if you received the character (ASCII encoded!) '1'
(the single quotes are for characters).
Note: It seems you want to switching the relay on and off until another character is send. Currently you are switching the relay 10 times a second. That is much for a relay, especially, if you are switching high voltages (like mains power). You should be aware, that this might cause problems with your relay after some time.