I'm working on my second Arduino project, and am somewhat stuck.
I'm running a PIR module from my Arduino Uno with the following sketch:
/*
* PIR Sensor test
*/
int pirPin = 6;
int minSecsBetweenEmails = 60; // 60 seconds
long lastSend = -minSecsBetweenEmails * 1000l;
void setup()
{
pinMode(pirPin, INPUT);
Serial.begin(9600);
}
void loop() {
long now = millis();
if (digitalRead(pirPin) == HIGH)
{
if (now > (lastSend + minSecsBetweenEmails * 1000l))
{
Serial.println("MOVEMENT");
lastSend = now;
}
else
{
Serial.println("Too soon");
}
}
delay(500);
}
I'm monitoring the COM3 port using the following in JupyterLab with PySerial.
import time
import serial
import smtplib
to = '[email protected]'
GMAIL_USER = '[email protected]'
GMAIL_PASS = '**********'
SUBJECT = 'MOTION pir'
TEXT = 'PIR sensor detected motion'
ser = serial.Serial('COM3', 9600)
def send_email():
print("Sending Email")
smtpserver = smtplib.smtp("smtp.gmail.com",587)
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.ehlo
smtpserver.login(GMAIL_USER, GMAIL_PASS)
header = str('To:' + TO + '\n' + 'From: ' + GMAIL_USER)
header = header + '\n' + 'Subject:' + SUBJECT + '\n'
print (header)
msg - header + '\n' + TEXT + ' \n\n'
smtpserver.sendmail(GMAIL_USER, TO, msg)
smtpserver.close()
while True:
message = ser.readline()
print(message.decode('utf-8'))
if message[0] == 'MOVEMENT' :
send_email()
time.sleep(0.5)
I believe my problem is with the ser.readline()
function. I've been reading the docs, they seem to say I need to provide some kind of endpoint or timeout for the function to provide for EOF, but my goal was to have the
if message [0] == 'MOVEMENT' :
continuously evaluate the output lines from COM3...
Any input at all would be very much appreciated.
EDIT: Thanks to all three of you for your help! By changing the Python as shown below I was able to fulfill the if message[0] == 'MOVEMENT' :
statement
Python should have been:
import time
import serial
import smtplib
to = '[email protected]'
GMAIL_USER = '[email protected]'
GMAIL_PASS = '**********'
SUBJECT = 'MOTION pir'
TEXT = 'PIR sensor detected motion'
ser = serial.Serial('COM3', 9600)
def send_email():
print("Sending Email")
smtpserver = smtplib.smtp("smtp.gmail.com",587)
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.ehlo
smtpserver.login(GMAIL_USER, GMAIL_PASS)
header = str('To:' + TO + '\n' + 'From: ' + GMAIL_USER)
header = header + '\n' + 'Subject:' + SUBJECT + '\n'
print (header)
msg - header + '\n' + TEXT + ' \n\n'
smtpserver.sendmail(GMAIL_USER, TO, msg)
smtpserver.close()
while True:
message = ser.readline()
print(message)
if message == b'MOVEMENT\r\n' :
send_email()
time.sleep(0.5)
1 Answer 1
You're confusing readlines()
with readline()
. The former returns an array of lines, the latter a single line. You need to drop the [0]
since you're not working with an array of lines, and you need to include the line endings that the Arduino sends:
while True:
message = ser.readline()
print(message.decode('utf-8'))
if message == 'MOVEMENT\r\n' :
send_email()
time.sleep(0.5)
-
Thanks Majenko. You're correct on my confusion between those functions. I've attempted to add the line ending characters but have yet to fulfill the if statement, so I'm going to continue investigating where I screwed up.Dylan Shroll-Tews– Dylan Shroll-Tews2019年08月02日 01:48:55 +00:00Commented Aug 2, 2019 at 1:48
millis()
rolls over. You should rather writeif (now - lastSend > minSecsBetweenEmails * 1000l)
, which is rollover-safe.millis()
rollover. I guess I misunderstood the breadth of this specific StackExchange community, I was under the impression that since I'm dealing with a specific Arduino implementation it would be relevant here, but I guess not. The Uno's output is exactly what I expect, so I'm thinking it's more of a Python issue. KIIV, as to your first comment, I've tried to add the line ending characters to the string since I'm getting the correct output from the Uno, but no luck yet.