Python implementation + Arduino Duemilanove ATMega328

Hi guys…as I progress with our interactive experience, I keep running into problems and questions pretty much every single day, this time with arduino…

instalation

Thank you,

António

easy way to do so is by using polling.

your reading software would then open the serial port.
like
ser = serial.Serial(’/dev/ttyUSB0’, 9600, timeout=0.1)
with the correct serial device, on windows you may simply use numbers.

now that you should be able to read and write chars on the serial device you can communicate in what ever way you want.
i usualy send a a start-byte (simply a char) to the controller, the controller reads it, checks the button states, and then answers with one or more chars containing the actual button states.

on the pc end it looks like:

data=[]
ser.flush()
ser.flushInput() #clears all buffers so no garbage is read or send
ser.write(chr(0xff))  #sends start-byto
for i in range(0,7): #for 7 byte long response
    inchar = ser.read() #reads response
    self.data.append(ord(inchar)) #and saves it as number

on the microcontroller end you would have something like:

while(1){
if(serial.read()==0xff){
serial.send(buttonStatus)
}
}

polling works a lot better with microcontrollers than events, especially if your reply is more than one byte long.
you may also want to keep the data transmitted over the comport low. 9600baud gives you about 1ms per byte of data. using higher baudrates and short responses is advised. also sending the new-data request right after finish reading on the pc is a good practice. altho you lack behind one frame with your input, the microcontroller wont block the panda thread that way.

is this what you mean on the microcontroller part:

const int button1Pin = 2; 		// the number of the pushbutton pin
const int button2Pin = 3;
const int button3Pin = 4;
const int button4Pin = 5;

// variables will change:
int buttonState[4]= {0}; 	// variable for reading the pushbutton status
int prevButtonState[4] = {0};

void setup()
{
   Serial.begin(9600); 
   // initialize the pushbutton pin as an input:
   pinMode(button1Pin, INPUT);
   pinMode(button2Pin, INPUT);
   pinMode(button3Pin, INPUT);
   pinMode(button4Pin, INPUT);     
}

void loop()
{
 buttonState[0] = digitalRead(button1Pin);
 buttonState[1] = digitalRead(button2Pin);
 buttonState[2] = digitalRead(button3Pin);
 buttonState[3] = digitalRead(button4Pin);

for(int i=0;i<4;i++)
  {
    Serial.println(buttonState[i]);
    delay(100);
  }
  
}

it’s reading 0’s and 1’s, 0000 no button pressed, 1111 all four buttons

now, figure out the pc part :slight_smile:

the microcontroller part is almost right.
you should add an if( Serial.read() ) before the for-loop. otherwise you will get a constant stream of 0 and 1 and you cant tell which number relates to which button.

other than that it is ok. you wont need the delay part in the final version tho, will only slow things down. so, at least my recommended logic goes like:
pc sends a char. microcontroller receives that and sends 4 chars back with the button info. microcontroller wont send any further data until a new char from the pc is received.

Thank you Thomas,

I changed the arduino code to:

const int button1Pin = 2;       // the number of the pushbutton pin 
const int button2Pin = 3; 
const int button3Pin = 4; 
const int button4Pin = 5; 

// variables will change: 
int buttonState[4]= {0};    // variable for reading the pushbutton status 
int prevButtonState[4] = {0}; 

void setup() 
{ 
   Serial.begin(9600); 
   // initialize the pushbutton pin as an input: 
   pinMode(button1Pin, INPUT); 
   pinMode(button2Pin, INPUT); 
   pinMode(button3Pin, INPUT); 
   pinMode(button4Pin, INPUT);      
} 

void loop() 
{ 
 buttonState[0] = digitalRead(button1Pin); 
 buttonState[1] = digitalRead(button2Pin); 
 buttonState[2] = digitalRead(button3Pin); 
 buttonState[3] = digitalRead(button4Pin); 

if( Serial.read() ){
for(int i=0;i<4;i++) 
  { 
    Serial.println(buttonState[i]); 
    //delay(100); 
  } 
}
} 

It seems to be reading 0’s and 1’s depending on the state of the button…in python side, i tried

#-*- coding:utf8 -*-
from serial import *
#import time

def main():
	ser=Serial('COM3')
	print ser
	ser.baudrate = 9600
	ser.open()

	data=[] 
	ser.flush() 
	ser.flushInput() #clears all buffers so no garbage is read or send 
	ser.write(chr(0xff))  #sends start-byto 
	for i in range(0,7): #for 7 byte long response 
	    inchar = ser.read() #reads response 
	    self.data.append(ord(inchar)) #and saves it as number
	if(data[0]=='0' and data[1]=='1'):
		print "bla"
		#data [button 0, 1, 2, 3]
	else:
		print "bla bla"
 #went wrong
if __name__=='__main__':
	main()

I know there’s something wrong with the self part but is that the logic?

you send 4 byte from the μc to the pc. but your pc coder reads 7 bytes. you should change that to 4 bytes in the for i in range() part.

you should also delete the self thing. it slipped in there from my code which was originialy part of a class

slight progress:

arduino code

const int button1Pin = 2;       // the number of the pushbutton pin 
const int button2Pin = 3; 
const int button3Pin = 4; 
const int button4Pin = 5; 
const char pin1d=0x01;
const char pin2d=0x02;
const char pin3d=0x04;
const char pin4d=0x08;

// variables will change: 
int buttonState[4]= {0};    // variable for reading the pushbutton status 
int prevButtonState[4] = {0}; 

void setup() 
{ 
   Serial.begin(9600); 
   // initialize the pushbutton pin as an input: 
   pinMode(button1Pin, INPUT); 
   pinMode(button2Pin, INPUT); 
   pinMode(button3Pin, INPUT); 
   pinMode(button4Pin, INPUT);      
} 

void loop() 
{ 
  //if(Serial.available()>0){
  //  if(Serial.read()==0xFF){
         char retValue=0;
         retValue=digitalRead(button1Pin)==1?retValue|pin1d:retValue&~pin1d;
         retValue=digitalRead(button2Pin)==1?retValue|pin2d:retValue&~pin2d;
         retValue=digitalRead(button3Pin)==1?retValue|pin3d:retValue&~pin3d;
         retValue=digitalRead(button4Pin)==1?retValue|pin4d:retValue&~pin4d;
         Serial.print(retValue);
  //  }
  //}
}

python

#-*- coding:utf8 -*-
from serial import *
#import time

def main():
	ser=Serial('COM3',9600)
	print ser
	
	while 1:
		#data=[] 
		ser.flush() 
		ser.flushInput() #clears all buffers so no garbage is read or send 
		print ord(ser.read(size=1))  #sends start-byto 
if __name__=='__main__':
	main()

i can now read bytes of information from the buttons but there’s still a lot of trash going on…i wonder if it’s possible to read just the state…either x button is pressed or released