June 05, 2012 by ead3281 I just completed a project that uses an ultrasonic ping sensor. The distance from the sensor is used to position a paddle in a pong game. Pygame is used to make the pong interface. I used the code from a pygame tutorial example called chimp.py(see- www.pygame.org/docs/). It was great fun building the project and its a blast to play pong by running back and forth across the room. The code is shown below. Sorry if it is a little lengthy, I tried to insert comments to explain what was going on Here's the C code for the microcontroller ``````// ping.c // for NerdKits with ATmega168 // //05/29/2012 //This code was written to operate a parallax ping sensor //It implements a timer and external interrupts via pin PCO //The ping sensor has only one data line so PCO must be operated //both in read and write mode //It ouputs the objects distance via the uart #define F_CPU 14318180//Note I'm using a different crystal than supplied //with nerdkit #include //Needed for PSTR function #include #include #include #include "../libnerdkits/uart.h" #include "../libnerdkits/delay.h" #include "../libnerdkits/lcd.h" uint16_t counter=0; uint16_t int_counter=0;//intervals between pings are 25ms (.01ms*2500) double time; ISR(TIMER1_COMPA_vect)//this is the interrupt handler, gets called by the timer { if (counter==0){ PCICR &= ~(1<80){ //Ping sensor outputs a pulse whose length corresponds to distance of object //The leading edge of the pulse occurs at .79 ms thats where the //79.0(below) and 80 (above) come from // The rest of the math is due to the speed of sound //being 340 m/s. The .00001 refers to .01 ms which are the increments //of the timer. The factor of two is due to the sound has to go to //the sensed object and return to the sensor float distance=(counter-79.0)*340*.00001/2; printf_P(PSTR("%.2fM\r\n"),distance); } } int main() { // start up the serial port uart_init(); FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW); stdin=stdout=&uart_stream; //I am going to add some code to try and generate a timestamp TCCR1B |=(1< self.area.right: self.moveX=-self.B_SPEED newpos = self.rect.move((self.moveX, self.moveY)) if self.rect.top < self.area.top: self.moveY = self.B_SPEED newpos = self.rect.move((self.moveX, self.moveY)) if self.rect.bottom>self.area.bottom: self.moveY = -self.B_SPEED newpos = self.rect.move((self.moveX, self.moveY)) self.rect = newpos return state def main(): """this function is called when the program starts. it initializes everything it needs, then runs in a loop until the function returns.""" #Initialize Everything pygame.init() screen = pygame.display.set_mode((800, 600)) pygame.display.set_caption('Back to the Seventies') pygame.mouse.set_visible(0) #Create The Backgound background = pygame.Surface(screen.get_size()) background = background.convert() background.fill((250, 250, 250)) #Put Text On The Background, Centered if pygame.font: font = pygame.font.Font(None, 20) text = font.render("And we're off", 1, (10, 10, 10)) textpos = text.get_rect(centerx=background.get_width()/2) background.blit(text, textpos) #Display The Background screen.blit(background, (0, 0)) pygame.display.flip() #Prepare Game Objects clock = pygame.time.Clock() chimp = Chimp() paddle=Paddle() allsprites = pygame.sprite.RenderPlain( chimp,paddle) #Main Loop going = True while going: clock.tick(60) #Handle Input Events pygame.event.pump() keystate = pygame.key.get_pressed() if keystate[K_ESCAPE] or pygame.event.peek(QUIT): going=False direction = keystate[K_UP] - keystate[K_DOWN] paddle.move(direction) allsprites.update() paddlerect=[paddle.rect] x=chimp.rect.collidelist(paddlerect) if x==0: #print "we have contact" chimp.collide() #Draw Everything screen.blit(background, (0, 0)) allsprites.draw(screen) pygame.display.flip() pygame.quit() #Game Over #this calls the 'main' function when this script is executed if __name__ == '__main__': main() `````` Ooops, I forgot I was modifying the pygame code so that the ball would speed up every five paddle hits and I had taken out the code that reads in the serial input. Here's what the main loop in the bottom of the pygame code should be to read the serial input and move the paddle ``````#Main Loop going = True s = serial.Serial("/dev/ttyUSB0", 115200) while going: x=s.readline() str_m=x.split('M') paddle_x= int(eval(str_m[0])*100) clock.tick(60) #Handle Input Events pygame.event.pump() keystate = pygame.key.get_pressed() if keystate[K_ESCAPE] or pygame.event.peek(QUIT): going=False direction = keystate[K_UP] - keystate[K_DOWN] paddle.move(direction) allsprites.update() paddlerect=[paddle.rect] x=chimp.rect.collidelist(paddlerect) if x==0: print "we have contact" chimp.collide() #Draw Everything paddle.rect.topleft = (10,600-(paddle_x-50)*3) screen.blit(background, (0, 0)) allsprites.draw(screen) pygame.display.flip() pygame.quit() #Game Over #this calls the 'main' function when this script is executed if __name__ == '__main__': main() `````` Sorry for the earlier mix-up