Pages: [1]   Go Down
Author Topic: arduino restarts with incoming Serial data..help?  (Read 1876 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 10
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hi! im doing an LED Matrix Email Notifier which involves using python script.

the python script fetches the number of unread emails from my Gmail account every few minutes, and then sends it to my arduino (through pySerial extension). The arduino identifies the data, converts it into displays.

the problem is:
whenever python sends serial data ,my Arduino freezes up and restarts itself, it didn't receive any data at all.

but it got the data fine when i tried sending some random values through the serial monitor.

help!any idea why this happened?

python script taken from: http://kodeclutz.blogspot.com/2009/02/gmail-notifier-on-arduino.html
Code:
import httplib
import getpass
import base64
import re
import time
import serial

INTERVAL = 1  # check every INTERVAL minutes

serv = 'mail.google.com'
path = '/mail/feed/atom'

auth = base64.encodestring(
                '%s:%s'%(raw_input('Username: '),
                getpass.getpass()))

def count(data):
 matches = re.findall('<fullcount>([0-9]+)</fullcount>', data)
 if len(matches) == 0:
     print 'Error in parsing feed, check user name and password are correct'
     return 0
 return int(matches[0])

def getfeed():
 print 'Checking...'
 conn = httplib.HTTPSConnection(serv)
 conn.putrequest('GET', path)
 conn.putheader('Authorization', 'Basic %s'%auth)
 conn.endheaders()
 return conn.getresponse().read()

def writeSer(data):
 try:
     ser = serial.Serial('COM6')
     ser.write(data)
 except serial.serialutil.SerialException:
     print 'Error writing to serial device'
     raise

last_check = time.time() - INTERVAL*60 # subtract so that we check first time

while True:
    if time.time() - last_check < INTERVAL*60:
        continue
    last_check = time.time()
    msgs = count(getfeed())
    print type(msgs)
    print msgs,'mails'
    writeSer(str(msgs))



LED Matrix
Code:
//code courtesy of Hari Wiguna
//http://g33k.blogspot.com/

//-- Columns (Negative Cathodes) --
int latchPin1 = 2; //Arduino pin connected to Green Latch 12 ST_CP / RCK of 74HC595
int clockPin1 = 3; //Arduino pin connected to Yellow Clock 11 SH_CP / SCK of 74HC595
int dataPin1 = 4;  //Arduino pin connected to Blue Data 14 DS / SI of 74HC595

//-- Rows (Positive Anodes) --
int latchPin2 = 5; //Arduino pinn connected to Green Latch 12 ST_CP / RCK of 74HC595
int clockPin2 = 6; //Arduino pin connected to Yellow Clock 11 SH_CP / SCK of 74HC595
int dataPin2 = 7;  //Arduino pin connected to Blue Data 14 DS / SI of 74HC595

//=== B I T M A P ===
//Bits in this array represents one LED of the matrix
// 8 is # of rows, 7 is # of LED matrix we have
byte bitmap[8][4]; // Change the 7 to however many matrices you want to use.
int numZones = sizeof(bitmap) / 8; // I will refer to each group of 8 columns (represented by one matrix) as a Zone.
int maxZoneIndex = numZones-1;
int numCols = numZones * 8;

//=== F O N T ===
// Font courtesy of aspro648
// http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1203747843/22
// First char is @, next is A, B, etc.  Only lower case, no symbols.  
// The @ will display as space character.
byte alphabets[][5] = {
  {0,0,0,0,0},                  //'.' but replaced as 'blank,space'
  {1, 6, 8, 48, 64},            //'/'
  {62, 69, 73, 81, 62},         //0 - zero
  {0, 33, 127, 1, 0},           //1
  {49, 67, 69, 73, 49},         //2
  {34, 65, 73, 73, 54},         //3
  {24, 104, 8, 127, 8},         //4
  {114, 73, 73, 73, 70},        //5
  {62, 73, 73, 73, 38},         //6
  {64, 64, 71, 72, 112},        //7
  {54, 73, 73, 73, 54},         //8
  {50, 73, 73, 73, 62},         //9
  {0, 54, 54, 0, 0},            //:
  {0, 53, 54, 0, 0},            //;
  {8, 28, 54, 99, 65},          //<
  {34, 34, 34, 34, 34},         //=
  {65, 99, 54, 28, 8},          //>
  {32, 64, 77, 72, 48},         //?
  {62, 77, 85, 93, 60},        //@
  {31, 36, 68, 36, 31},            //A
  {127, 73, 73, 73, 54},      //B
  {62, 65, 65, 65, 34},            //C
  {127, 65, 65, 34, 28},      //D
  {127, 73, 73, 65, 65},        //E
  {127, 72, 72, 72, 64},      //F
  {62, 65, 65, 69, 38},            //G
  {127, 8, 8, 8, 127},            //H
  {0, 65, 127, 65, 0},            //I
  {2, 1, 1, 1, 126},            //J
  {127, 8, 20, 34, 65},            //K
  {127, 1, 1, 1, 1},            //L
  {127, 32, 16, 32, 127},      //M
  {127, 32, 16, 8, 127},      //N
  {62, 65, 65, 65, 62},            //O - not zero
  {127, 72, 72, 72, 48},      //P
  {62, 65, 69, 66, 61},            //Q
  {127, 72, 76, 74, 49},      //R
  {50, 73, 73, 73, 38},            //S
  {64, 64, 127, 64, 64},      //T
  {126, 1, 1, 1, 126},            //U
  {124, 2, 1, 2, 124},            //V
  {126, 1, 6, 1, 126},            //W
  {99, 20, 8, 20, 99},            //X
  {96, 16, 15, 16, 96},            //Y
  {67, 69, 73, 81, 97},            //Z
};

//=== S E T U P ===

void setup() {
  
  Serial.begin(9600);
  
  pinMode(latchPin1, OUTPUT);
  pinMode(clockPin1, OUTPUT);
  pinMode(dataPin1, OUTPUT);

  pinMode(latchPin2, OUTPUT);
  pinMode(clockPin2, OUTPUT);
  pinMode(dataPin2, OUTPUT);
  
  //-- Clear bitmap --
  for (int row = 0; row < 8; row++) {
    for (int zone = 0; zone <= maxZoneIndex; zone++) {
      bitmap[row][zone] = 0;
    }
  }
}

//=== F U N C T I O N S ===

// This routine takes whatever we've setup in the bitmap array and display it on the matrix
void RefreshDisplay()
{
  for (int row = 0; row < 8; row++) {
    int rowbit = 1 << row;
    digitalWrite(latchPin2, LOW);  //Hold latchPin LOW for as long as we're transmitting data
    shiftOut(dataPin2, clockPin2, MSBFIRST, rowbit);   //Transmit data

    //-- Start sending column bytes --
    digitalWrite(latchPin1, LOW);  //Hold latchPin LOW for as long as we're transmitting data

    //-- Shift out to each matrix (zone is 8 columns represented by one matrix)
    for (int zone = maxZoneIndex; zone >= 0; zone--) {
      shiftOut(dataPin1, clockPin1, MSBFIRST, bitmap[row][zone]);
    }

    //-- Done sending Column bytes, flip both latches at once to eliminate flicker
    digitalWrite(latchPin1, HIGH);  //Return the latch pin high to signal chip that it no longer needs to listen for information
    digitalWrite(latchPin2, HIGH);  //Return the latch pin high to signal chip that it no longer needs to listen for information
    
    //-- Wait a little bit to let humans see what we've pushed out onto the matrix --
    delayMicroseconds(500);
    
  }
}

// Converts row and column to actual bitmap bit and turn it off/on
void Plot(int col, int row, bool isOn)
{
  int zone = col / 8;
  int colBitIndex = col % 8;
  byte colBit = 1 << colBitIndex;
  if (isOn)
    bitmap[row][zone] =  bitmap[row][zone] | colBit;
  else
    bitmap[row][zone] =  bitmap[row][zone] & (~colBit);
}

// Plot each character of the message one column at a time, updated the display, shift bitmap left.
void AlphabetSoup(){
  
  byte email;
  
  if (Serial.available() > 0) {email = Serial.read();}
  else {email = 0;}
  
  char msg[6];
  sprintf ( msg, "%d mails", email );

  for (int charIndex=0; charIndex < (sizeof(msg)-1); charIndex++)
  {
    int alphabetIndex = msg[charIndex] - '.';          // The Fonts starts from ascii table of '/' until 'Z'. refer to ascii table here - http://www.asciitable.com
    if (alphabetIndex < 0) alphabetIndex=0;
    
    //-- Draw one character of the message --
    // Each character is only 5 columns wide, but I loop two more times to create 2 pixel space betwen characters
    for (int col = 0; col < 7; col++)
    {
      for (int row = 0; row < 8; row++)
      {
        // Set the pixel to what the alphabet say for columns 0 thru 4, but always leave columns 5 and 6 blank.
        bool isOn = 0;
        if (col<5) isOn = bitRead( alphabets[alphabetIndex][col], 7-row ) == 1;
        Plot( numCols-1, row, isOn); // We ALWAYS draw on the rightmost column, the shift loop below will scroll it leftward.
      }
      
      //-- The more times you repeat this loop, the slower it would scroll --
      for (int refreshCount=0; refreshCount < 10; refreshCount++)
        RefreshDisplay();

      //-- Shift the bitmap one column to left --
      for (int row=0; row<8; row++)
      {
        for (int zone=0; zone < numZones; zone++)
        {
          // This right shift would show as a left scroll on display because leftmost column is represented by least significant bit of the byte.
          bitmap[row][zone] = bitmap[row][zone] >> 1;
          
          // Roll over lowest bit from the next zone as highest bit of this zone.
          if (zone < maxZoneIndex) bitWrite(bitmap[row][zone], 7, bitRead(bitmap[row][zone+1],0));
        }
      }
    }
  }
}

//=== L O O P ===

void loop() {
  AlphabetSoup();
}

oh,and pardon for the bad english =P


« Last Edit: November 29, 2010, 08:28:57 am by keyvleon » Logged

0
Offline Offline
God Member
*****
Karma: 39
Posts: 988
Get Bitlash: http://bitlash.net
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The Arduino restarts when you open the serial port, from Python or any other PC side code.  This is to facilitate reflashing.  Search the forum here, there are many posts.

If you delay in the Python script for a short time (perhaps 1000 ms) before performing IO to the port it may help.

-br
http://bitlash.net
http://entropymouse.com
Logged

Austin, TX
Offline Offline
Faraday Member
**
Karma: 71
Posts: 6146
Baldengineer
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Disable the auto-reset.
Logged

Capacitor Expert By Day, Enginerd by night.  ||  Personal Blog: www.baldengineer.com  || Electronics Tutorials for Beginners:  www.addohms.com

0
Offline Offline
Newbie
*
Karma: 0
Posts: 10
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
The Arduino restarts when you open the serial port, from Python or any other PC side code.  This is to facilitate reflashing.  Search the forum here, there are many posts.

If you delay in the Python script for a short time (perhaps 1000 ms) before performing IO to the port it may help.

open port > delay > and sends IO when arduino done resetting itself?

if so where should i put the delay function? i don't write/understand any python script myself, need a little help here?

Quote
Disable the auto-reset.
that would mean i have to modify my arduino.
if possible, id like to avoid doing that smiley-cry
« Last Edit: November 29, 2010, 09:41:48 am by keyvleon » Logged

Manchester (England England)
Online Online
Brattain Member
*****
Karma: 625
Posts: 34106
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
if possible, id like to avoid doing that
The only way this is not possible is if you rewrite the serial port drivers on your PC. A task that is probably beyond you.
Logged

nr Bundaberg, Australia
Online Online
Tesla Member
***
Karma: 126
Posts: 8512
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I've never seen a single line of python code in my life so take this with a grain of salt, but looking at the following lines

    ser = serial.Serial('COM6')
    ser.write(data)

Does the first one open the port? If so add the delay after that and before the write.

______
Rob

Logged

Rob Gray aka the GRAYnomad www.robgray.com

0
Offline Offline
Newbie
*
Karma: 0
Posts: 12
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here is the modified code:
Code:
import httplib
import getpass
import base64
import re
import time
import serial

ser = serial.Serial()
ser.port = 'COM6'

try:
    ser.open()
    time.sleep(1.5) # run some test to find the proper delay here
except serial.serialutil.SerialException:
    print 'Error opening serial port',ser.port
    raise

INTERVAL = 1  # check every INTERVAL minutes

serv = 'mail.google.com'
path = '/mail/feed/atom'

auth = base64.encodestring('%s:%s'%(raw_input('Username: '),getpass.getpass()))

def count(data):
    matches = re.findall('<fullcount>([0-9]+)</fullcount>', data)
    if len(matches) == 0:
        print 'Error in parsing feed, check user name and password are correct'
        return 0
    return int(matches[0])

def getfeed():
    print 'Checking...'
    conn = httplib.HTTPSConnection(serv)
    conn.putrequest('GET', path)
    conn.putheader('Authorization', 'Basic %s'%auth)
    conn.endheaders()
    return conn.getresponse().read()

def writeSer(data):
    try:
         #ser = serial.Serial('COM6')
         ser.write(data)
    except serial.serialutil.SerialException:
         print 'Error writing to serial device'
         raise

last_check = time.time() - INTERVAL*60 # subtract so that we check first time

while True:
    if time.time() - last_check < INTERVAL*60:
        continue
    last_check = time.time()
    msgs = count(getfeed())
    print type(msgs)
    print msgs,'mails'
    writeSer(str(msgs))


You will probably want to close the serial before the program closes in case the program fails and hangs your serial port, but I will leave that up to you.

Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 12
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I wrote a little program to test how long it takes for an Uno to begin writing to the serial port after it is reset using the ugly code below.  The results showed that it took from 1.1089 to 1.1093 seconds +- 0.0001 seconds for the Arduino Uno to startup and begin running a small amount of code.  I have no doubt that the longer the code is, the longer the uC will take to initialize it.  So, if this hasn't been documented before, expect an Uno to take AT LEAST 1.11 seconds to initialize.

Python
Code:
# Written to determine how long an Arduino Uno takes
# to initialize from a RESET.

import serial
import time

# Configure Serial Port Settings
ser = serial.Serial()
ser.baudrate = 115200
ser.timeout = 1
ser.writeTimeout = 2
ser.port = 'COM25'

# Initialize Variables
a = []
b = 0

for x in range(0,25):          # Run test 25 times
    start = time.time()
    ser.open()
    while ser.inWaiting()==0:
        time.sleep(0.0001)     # Look for Serial data every 0.0001 seconds
    finish = time.time()       # Determine how long the reset took
    ser.close()
    a.append(finish-start)     # Add this runs time to the list

a.sort()                       # Sort list from low to high
for item in a:
    b += item
print "Average Time:",b / len(a)
print "Lowest Time :",a[0]
print "Highest Time:",a[-1]

Arduino
Code:
void setup() {
  Serial.begin(115200);
}

void loop() {
  Serial.println("x");
}


So, for real world testing, you may want to change your code as below just for testing and then comment out my added line later...

Arduino
Code:
 byte email;
  Serial.println("x"); // Comment this out later
  if (Serial.available() > 0) {email = Serial.read();}
  else {email = 0;}
Logged

Humboldt, CA
Offline Offline
Full Member
***
Karma: 2
Posts: 223
Arduino BBB
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

First a disclaimer:  This is going to require causing physical damage to your arduino if you do it my way.  On my boards (BBB and RBBB) i could mod the USB-BUB adapter.

What you'll need to do if you want to do it in hardware is find the trace that goes from the FTDI chip (or the small atmega chip on the Uno) to the reset wiring of the atmega.  Once you find it, cut it.  Make sure you cut between FTDI and the rest of the reset wiring, otherwise you may well disable the reset button as well.  Presto!  No more auto reset.
Downside:  You have to manually hit the reset button to upload a sketch now smiley-sad

It'd be nice to have a jumper or a little switch to set whether it auto-resets or not, maybe that'll be included in the Uno2.
Logged

Monterey CA
Offline Offline
Sr. Member
****
Karma: 1
Posts: 323
Addicted to Arduino
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I have found that using serial proxy for some reason doesn't cause the Arduino to reset on connection. But if you use it make sure and use the tinkerproxy version that has all the fixes.
« Last Edit: December 01, 2010, 11:29:12 pm by wgarrido » Logged

Current Projects:                    Arduinos:
Security Robot Tank               Uno
Security Robot II 4WD            Mega2560

http://mobilewill.blogspot.com

0
Offline Offline
Newbie
*
Karma: 0
Posts: 10
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks JimmyDB you rock! your modified code works out well and i do not have to modify my arduino! i'll make sure credit you for your help when my project is done =).

and id like to thank everybody as well for the great response, this is a great community =)
Logged

Pages: [1]   Go Up
Jump to: