Serial?

Sorry about the confusing topic. Please bear with me while I type out my background information/include screenshots.

Alright, so I wrote a python program to check my email, and categorize them according to author: uncategorized, Facebook Notifications, or Twitter Notifications. Next, it tries to send this information over serial to my Arduino. On the arduino end, however, nothing seems to happen... I can see the pin 13 LED light up as the serial port opens, (I think that's what is happening) then nothing.

import feedparser, requests, serial, sys

b = feedparser.parse(requests.get('https://mail.google.com/mail/feed/atom', auth=('gmailusername', 'gmailpassword')).content)

SERIALPORT = "COM3"

try:
    ser = serial.Serial(SERIALPORT, 9600)
except serial.SerialException:
    sys.exit()

mailcount = int(b['feed']['fullcount'])
facebook = int(0)
twitter = int(0)
print("Total mail: " + b['feed']['fullcount'])
if mailcount > 0:
    for entry in b['entries']:
        author = (entry['author'])
        if "postmaster.twitter.com" in author:
            twitter += 1
            mailcount -= 1
        if "facebookmail.com" in author:
            facebook += 1
            mailcount -= 1

print("Uncategorized mail: " + str(mailcount))
print("Facebook mail: " + str(facebook))
print("Twitter mail: " + str(twitter))

if mailcount > 0: ser.write(bytes('7', encoding='ascii'))
else: ser.write(bytes('MN', encoding='ascii'))

if facebook > 0: ser.write(bytes('FY', encoding='ascii'))
else: ser.write(bytes('FN', encoding='ascii'))

if twitter > 0: ser.write(bytes('TY', encoding='ascii'))
else: ser.write(bytes('TN', encoding='ascii'))

ser.close()

Screenshot of my Python code.

Screenshot of Python output.

int mailOut = 8;
int fbOut = 9;
int twitOut = 10;
int mail = LOW;
int fb = LOW;
int twit = LOW;
int val;

void setup()
{
    pinMode(mailOut, OUTPUT);
    pinMode(fbOut, OUTPUT);
    pinMode(twitOut, OUTPUT);
    Serial.begin(9600);
    Serial.flush();
}

void loop()
{
    if (Serial.available())
    {
        val = Serial.read();
        Serial.println(val);
        if (val == 'MY') mail = HIGH;
        else if (val == 'MN') mail = LOW;
    }
    digitalWrite(mailOut, mail);
}

And, finally, the Arduino code. Not sure what's going on.. maybe I'm just too tired to see the blaring problem.

Serial.read() only reads 1 byte at a time, so val will never equal what you ask

Another problem: The single quotes ' are used to surround a single character, not a string. So 'MY' will actually be seen as 'M'. If the Arduino IDE didn't hide all the warnings from you it'd have told you.

To work with strings you need to use the double quotes " and some of the string functions like strcmp

if (strcmp(val, "MY") == 0) {
  ...
}

But with val being an int that'd never work. You need to think more carefully about what you are trying to transfer and just how you are going to transfer it, given that serial only ever transfers one single byte at a time.

majenko: So 'MY' will actually be seen as 'M'.

Or 'Y' even, as it will throw away the high-order bytes.

[quote author=Nick Gammon link=topic=180986.msg1341641#msg1341641 date=1375605690]

majenko: So 'MY' will actually be seen as 'M'.

Or 'Y' even, as it will throw away the high-order bytes. [/quote] All depending on endianness of course... Let's not split hairs - it doesn't matter what it actually appears as, the simple fact is it won't be what the OP is expecting it to be, and so will be wrong.

Yep, it won’t be “MY” that’s for sure.

@OP: don't post screenshots of your code, copy and paste it inside code tags. Then we can quote it.

[quote author=Nick Gammon link=topic=180986.msg1341650#msg1341650 date=1375606217] @OP: don't post screenshots of your code, copy and paste it inside code tags. Then we can quote it. [/quote] We can also copy and paste it ourselves and compile it to try and replicate the problem ourselves. I can't think of anyone here that'd bother to type in all your code manually just to test it.

Try incorporating this into your code…
This will take chars from the buffer and add them to a string called serialInput
If you use this code you need to send your data surrounded by a ‘<’ and ‘>’
e.g or

const char startOfDelimiter = '<';
const char endOfDelimiter = '>';
String serialInput;
boolean allowInput = false;

//----------------------------------------------//

void setup(){ 
 	Serial.begin(9600);
 	pinMode(9, OUTPUT);
 	pinMode(10, OUTPUT);
 	pinMode(12, OUTPUT);
}

//----------------------------------------------//

void loop(){
	if(Serial.available()){
		digitalWrite(12, HIGH);
		processInput();
	}
	if(serialInput.compareTo("MY") == 0){
		digitalWrite(9, HIGH);
		digitalWrite(10, LOW);
	}else if(serialInput.compareTo("MN") == 0){
		digitalWrite(10, HIGH);
		digitalWrite(9, LOW);
	}
}

//----------------------------------------------//

void processInput(){
	char inputedChar = Serial.read();
 	switch(inputedChar){
	    case startOfDelimiter:	//Preps anything for an input
	    	serialInput = "";	//Clears "serialInput" ready for new input
	    	allowInput = true;	//Allows characters to be added to "serialInput" in the default case
	    	break;

	    case endOfDelimiter:	
	    	allowInput = false;
	    	while(Serial.available()){	// Clears the buffer of any extra junk after the end delimiter
	   			Serial.read();			//
	   		}							//
	    	break;

	    default:	
	    	if(allowInput == true){	// Add the inputed chars to the string if the starting delimiter has been sent
	    		serialInput = serialInput + inputedChar;
	    	}else{
	    		while(Serial.available()){	//Clears the buffer
	   				Serial.read();
	   			}
	    	}
	    	break;
  	}
}

P.S I know this is going to keep adding chars to the string… going to fix it and repost
Should Will work now!
P.P.S can an admin look into making tab stops equivalent to 2-4 spaces.

Serial_Test_Forum.ino (1.43 KB)

I dunno who to quote, since you're all helping me out quite a bit so I'll just throw this out here... I don't really mind if it doesn't send the data as "MY" or "MN" or whatever. I assume if I send M from Python encoded as ASCII, serial.read would need to return a number? Also, edited the OP with code tags.

Tried tigerbomb's solution and it didn't seem to work. Pin 12 NEVER even goes high.

tssguy123:
I dunno who to quote, since you’re all helping me out quite a bit so I’ll just throw this out here… I don’t really mind if it doesn’t send the data as “MY” or “MN” or whatever. I assume if I send M from Python encoded as ASCII, serial.read would need to return a number? Also, edited the OP with code tags.

Tried tigerbomb’s solution and it didn’t seem to work. Pin 12 NEVER even goes high.

I tested it with the arduino IDE serial monitor and is seems to work fine
You need to import the time library and then call the following code before you try to send anything but after you have opened the port. This will give enough time for the Arduino to reset

import time

time.sleep(2)

here is an example

import time, serial, sys

SERIALPORT = "COM3"

ser = serial.Serial(SERIALPORT, 9600)
time.sleep(2)
ser.write('<')
ser.write('M')
ser.write('Y')
ser.write('>')

ser.close()

On the arduino end, however, nothing seems to happen... I can see the pin 13 LED light up as the serial port opens, (I think that's what is happening) then nothing.

Very simple serial delimited code that captures command characters from the arduino serial in, evaluates the captured String, then operates the arduino LED based on the command sent.

//zoomkat 3-5-12 simple delimited ',' string parse 
//from serial port input (via serial monitor)
//and print result out serial port
// CR/LF could also be a delimiter
//send on, or off, from the serial monitor to operate LED

int ledPin = 13;
String readString;

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT); 
  Serial.println("serial LED on/off test with , delimiter"); // so I can keep track
}

void loop() {

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      Serial.println(readString); //prints string to serial port out
      //do stuff with the captured readString
      if(readString.indexOf("on") >=0)
      {
        digitalWrite(ledPin, HIGH);
        Serial.println("LED ON");
      }
      if(readString.indexOf("off") >=0)
      {
        digitalWrite(ledPin, LOW);
        Serial.println("LED OFF");
      }       
      readString=""; //clears variable for new input
    }  
    else {     
      readString += c; //makes the string readString
    }
  }
}

tigerbomb8:

tssguy123:
I dunno who to quote, since you’re all helping me out quite a bit so I’ll just throw this out here… I don’t really mind if it doesn’t send the data as “MY” or “MN” or whatever. I assume if I send M from Python encoded as ASCII, serial.read would need to return a number? Also, edited the OP with code tags.

Tried tigerbomb’s solution and it didn’t seem to work. Pin 12 NEVER even goes high.

I tested it with the arduino IDE serial monitor and is seems to work fine
You need to import the time library and then call the following code before you try to send anything but after you have opened the port. This will give enough time for the Arduino to reset

import time

time.sleep(2)



here is an example


import time, serial, sys

SERIALPORT = “COM3”

ser = serial.Serial(SERIALPORT, 9600)
time.sleep(2)
ser.write(’<’)
ser.write(‘M’)
ser.write(‘Y’)
ser.write(’>’)

ser.close()

PERFECT! Awesome, thank you SO much.
Now, however, my issue is that the LED flickers on/off twice before it sticks on/sticks off.

You do know that every time you open the serial connection to the Arduino it reboots the Arduino, don't you?

majenko: You do know that every time you open the serial connection to the Arduino it reboots the Arduino, don't you?

Now I do. That's kind of irritating.

majenko: You do know that every time you open the serial connection to the Arduino it reboots the Arduino, don't you?

Not on all boards, I think.

I suppose there's some sort of circuit I can do that will prevent short pulses like that?

tssguy123: I suppose there's some sort of circuit I can do that will prevent short pulses like that?

I usually use a 10uF capacitor between RESET and GND, but there are other methods too.

majenko:

tssguy123: I suppose there's some sort of circuit I can do that will prevent short pulses like that?

I usually use a 10uF capacitor between RESET and GND, but there are other methods too.

That's all I have to do? Put a 10 microfarad between reset and ground and it won't flash the LEDs anymore?

tssguy123:

majenko:

tssguy123: I suppose there's some sort of circuit I can do that will prevent short pulses like that?

I usually use a 10uF capacitor between RESET and GND, but there are other methods too.

That's all I have to do? Put a 10 microfarad between reset and ground and it won't flash the LEDs anymore?

The capacitor absorbs the reset pulse enough to not reset the Arduino. However, you won't then be able to program the board without pressing the reset button at just the right moment. So, make the capacitor removable :)