NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » Python Help

March 24, 2011
by kemil
kemil's Avatar

Dear all,

I am trying to create a GUI for a project i want to do. In theory its really simple, I just want to be able to change the intensity of a high powered LED using PWM by changing the value of the OCR1BL register from 0 to 255.

The thing is I know absolutely nothing about python. So could anyone recommend me the following:

  • Where to install python from.
  • How to get it up and running
  • Tutorials on how to create the GUI
  • How to interface the GUI with my microcontroller

Many thanks

Kemil

March 24, 2011
by Ralphxyz
Ralphxyz's Avatar

So the first question is do you have the microcontroller part using PWM and say a potentiometer working, forgetting python?

Then where does the GUI come in? Do you want to have a graphical slider that you move on the pc that would brighten the led connected to the micro.

There are threads here in the forum on setting up python. As far as how to setup the GUI go to the python forums.

You will get other replies here but to get in depth help you probable will need to go to a python specific forum.

Ralph

March 24, 2011
by kemil
kemil's Avatar

Hi Ralph,

Yes - 'a graphical slider that you move on the pc that would brighten the led connected to the micro' is exactly what im after.

I am confident i have the hardware side of things set up. As im using High power LEDs i have to use some LED drivers which are connected to a power supply unit. The LED driver has a dim connection which is where the microcontroller with its PWM port comes into play.

The problem is i dont know how to interface the MCU with my PC running the python GUI, (or how to make the GUI its self). How does the python script update the OCR1BL register on the MCU? i guess im looking for a blow-by-blow explanation of the interaction between the two.

Thanks Kemil

March 24, 2011
by Ralphxyz
Ralphxyz's Avatar

I think I started out with the python code for the Weight Scale and the PS2 Keyboard Tutorial. The weight scale shows you how to show a graph using Python and the PS2 Keyboard shows you how to talk to a micro using UART.

I am not a Python programmer but those two projects should help you to get going.

Building a GUI is a very interesting idea so please keep us posted on your progress.

Ralph

March 24, 2011
by hevans
(NerdKits Staff)

hevans's Avatar

Hi Kemil,

Here are a few things to get you started.

Python Download site. I am pointing you directly to the python 2.6 download which is the latest version that is still compatible with PyGame

PyGame download site. PyGame is a module for Python that makes it easier to write GUIs. It's one of our favorites although there are others out there. Make sure you get Python.

The PyGame website has a whole bunch of tutorials that are great to get started, and their documentation is very usable.

Definitely do take a look at the links Ralph pointed you to.

Humberto

March 25, 2011
by kemil
kemil's Avatar

Thanks Humberto,

Can i just confirm, before i start spending time building this GUI, that it is theoretically possible to change the brightness on an LED through a GUI on my PC, whilst the microcontroller is running?

Kemil

March 25, 2011
by Rick_S
Rick_S's Avatar

It would be absolutely possible. The GUI on your PC would just output serial data to the micro that it would interpret to the various brightness levels.

Rick

April 05, 2011
by kemil
kemil's Avatar

Does anyone know any good tutorials on how a python script running on the pc interfaces with the microcontroller?

kemil

April 07, 2011
by kemil
kemil's Avatar

Hi all,

Ive just been playing around with the tempsensor porject to get a feel for how serial connections work and have run into a problem. Using Putty (im using windows vista) I can get the temperature reading to be displayed on my PC. However when it comes to using the Python script from the meat thermometer tutorial it doesn't work properly.

Im stilly trying to learn python and am not good enough yet to figure out the problem. This is what my command prompt shows when i initially run pc-pygame.py

Alt Text

As you can see some temperature vaulus come up but the graph remains un altered. Then after about a minute this comes up on my command prompt

Alt Text

I assume (although i have no idea) that there is something wrong in the python code beauce i can get values on putty, however, I got the python code straight from the nerdkits website and only changed the line:

self.s = serial.Serial("COM4", 115200) (chenged version)

As this is the port i am using and the baud rate, as stated in the servo tutorial, should be 115200.

Any Ideas of what is going on anyone?

Many Thanks

Kemil

April 11, 2011
by kemil
kemil's Avatar

Hi all,

This is where i am up to with my little project. I have written the python code which produces a little GUI shown in the photo below.

Alt Text

As you can see the slider goes from 0 to 255 which corresponds to the different OCR1BL levels which will determine the PWM rate and hence the brghtness of the LED.

On the command prompt in the same picture you can see that i have managed to print out the values which show up on the slider. My thinking is that i could just put this variable called brightness into the piece of code:

ser = serial.Serial("COM4", 115200, timeout=1)
time.sleep(1.5)
ser.write(brightness)

which would port it onto the microcontroler.

I got this from the web but not sure if its this simple.

I am now stuck on how i am meant to set OCR1BL equal to brightness whilst the microcontroller is running. Am i meant to use an interrupt? if so how is this done?

Cheers

Kemil

April 11, 2011
by hevans
(NerdKits Staff)

hevans's Avatar

Hi Kemil,

You have gotten pretty far, now is the time you get into the real meat of you project. Varying the brightness of an LED through PWM is not a very hard thing to do, but wrapping your head around some of the concepts can be tricky. You will have to structure your program in such a way that the main loop reads a new value from the serial port, and then simply sets the value of the PWM duty cycle right after. No interrupts should be necessary unless you want to do other things while waiting for the serial value to be read. Hope that helps.

Humberto

April 12, 2011
by kemil
kemil's Avatar

Thanks Humberto,

I think my problem is i dont conceptually understand what is happening to the data as it is sent over the serial port, i.e what form is the data sent in etc.

the code im am using to send and receive my data is as follows: On the python side i have the lines

ser = serial.Serial("COM4", 115200)
ser.write(brightness)

which im hoping is sending the vairable 'brightness' over the serial port

Whilst the code on the MCU side:

#define F_CPU 14745600

#include <stdio.h>
#include <math.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>

#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"
#include "../libnerdkits/uart.h"

int main(void)

{
volatile uint8_t brightness ;
DDRB |= (1<<PB2);         
TCCR1A = (1<<COM1B1)|(1<<1);   
TCCR1B = 1;

OCR1BH = 0;
uart_init();
FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
stdin = stdout = &uart_stream;

while(1) {

scanf_P(PSTR("%u"), &brightness);
OCR1BL = brightness;
}
return 0;
}

I hope is receiving this data and assigning this 'brightness' variable to OCR1BL. However, the code above doesnt work, and im not sure why not.

As you can see ive set up the PWM register and declared a unsigned integer called brightness, i think i have set up the serial port with the uart_init(); command and the 2 lines underneith. Then in the while loop i use the scanf command to capture the data coming over the serial port... im pretty sure this part is wrong... but i dont know how to make it right.

Anyone have anyideas of what the MCU code should look like?

Thanks

Kemil

April 12, 2011
by kemil
kemil's Avatar

I have modified the C code. I can get the LED to turn on using the scroller but it does not change the intensity.

new C code is: int main(void)

{
uart_init();
FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
stdin = stdout = &uart_stream;

char brightness;

DDRB |= (1<<PB2);         
TCCR1A = (1<<COM1B1)|(1<<1);   
TCCR1B = 1;

OCR1BH = 0;

while(1) {

brightness = uart_read();

OCR1BL = brightness;

}
return 0;
}

Kemil

April 12, 2011
by kemil
kemil's Avatar

GOT IT TO WORK! for all those who are interested. i altered the python code bit to:

ser = serial.Serial("COM4", 115200)
ser.write(str(int(brightness)))
ser.write("\n")

and the c code is

int main(void)

{
uart_init();
FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
stdin = stdout = &uart_stream;

int brightness ;
int16_t newbright;
DDRB |= (1<<PB2);         
TCCR1A = (1<<COM1B1)|(1<<1);   
TCCR1B = 1;

OCR1BH = 0;

while(1) {
 //brightness = uart_read();
newbright = scanf_P(PSTR("%d"), &brightness);

OCR1BL = brightness;
  }
return 0;
}

If anyone wants to optomise it or suggest any improvements then be my guest

kemil

April 12, 2011
by Ralphxyz
Ralphxyz's Avatar

Thanks kemil, that will come in handy one of these day. Would you post a link to your whole project or at least the basic python code to make the slider, the serial communications and then the mcu code.

I do not understand your logic of passing the variable "brightness" instead just passing the brightness value but you got it to work, that's great.

Ralph

April 18, 2011
by kemil
kemil's Avatar

It is possible to send and receive data over the serial port at the same time? I want to combine the Light dimmer widget with the temp sensor project.. but this would required me to send data to the MCU whilst also reading from it.. Anyone know how i should go about doing this?

Kemil

April 18, 2011
by Ralphxyz
Ralphxyz's Avatar

Isn't that what USART does?

or is it UART that does the simultaneous communications.

Ralph

April 18, 2011
by hevans
(NerdKits Staff)

hevans's Avatar

H Kemil,

Ralph is right, you should be able to read and write through the serial port at the same time with no problem. On the computer end you will have to make sure the same process is doing both the reading and the writing as only program can keep the device open at the same time, but other than that it should be straight forward.

Humberto

May 05, 2011
by kemil
kemil's Avatar

Hi Humberto,

When u guys say use USART instead does this mean i have to do something similar to what u have done with UART in the libnerdkits folder? has anyone writtten a function similar to that of uart_init() but for USART... even once reading the data sheet i dont know what bits on what registers to turn on and off in order to do what i want.

Thanks Kemill

May 05, 2011
by kemil
kemil's Avatar

Just tried it with the uart_init for libnerdkits and it works. but i have a bigger problem

Im using a modified version of the tempsensor code where ive just added an if statement which turns on an led if the temp is above a certain value.

Ive written a short python code which allows me to change the minimum temperature which turns on the led: the python code is:

import serial
import time
from Tkinter import *
from Dialog import Dialog

root = Tk()
root.title("Temp Entry box")
enter_data_1 = Entry(root, bg = "pale green")
enter_data_1.grid(row=1, column=1)
enter_data_1.insert(0,"enter text here")

ser = serial.Serial("COM4", 115200)

def callback_origin():
   data_inp_1 = enter_data_1.get()
   label_2_far_right = Label(root, text=data_inp_1)
   label_2_far_right.grid(row=1, column = 3)

   ser.write(str(int(data_inp_1)))
   ser.write("\n")
   x = ser.readline()
   print x

but1= Button(root, text="press to   transfer",/
command=callback_origin).grid(row=5,column=0)

root.mainloop()

This kind of worked but it wouldnt give me the continuous stream of data which i was looking for (i was able to change the data_inp_1 value in the if statement: if (temp_avg > data_inp_1 ) though, which is good) ... instead it only gave me the temp reading when i pressed the button.... i think this is because the print command is only called when the button is pushed.... so i tried moving the ser.readline and the print x commands but doing this made the gui not even come up!

I looked through the pc-pygame python code for the meat thermom project and it uses the threading module... im not sure how to implement this module and i have i hunch its what i need to do, i tried playing around with it to no avail....

Does anyone know what i need to do to be able to print out continuouse stream of temperatures?

Thanks

Kemill

May 05, 2011
by kemil
kemil's Avatar

UPDATE: I think ive narrowed down the problem... its def something to do wtih my code, shown below: i have changed my python code so i just print out the temp values. This ONLY works successfully when i comment out the scanf_P line in my code. when i uncomment it and runt the same code it doesnt work.

The question is how do i simaltaneously send and receive data from the mcu.. whos got the code to do so?

Thanks Kemill

#define F_CPU 14745600

#include <stdio.h>
#include <math.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>

#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"
#include "../libnerdkits/uart.h"

// PIN DEFINITIONS:
//
// PC0 -- temperature sensor analog input

void adc_init() {
// set analog to digital converter
// for external reference (5v), single ended input ADC0
//ADMUX = 0;

// set analog to digital converter
// to be enabled, with a clock prescale of 1/128
// so that the ADC clock runs at 115.2kHz.
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);

// fire a conversion just to get the ADC warmed up
ADCSRA |= (1<<ADSC);
}

uint16_t adc_read() {
// read from ADC, waiting for conversion to finish
// (assumes someone else asked for a conversion.)
// wait for it to be cleared
while(ADCSRA & (1<<ADSC)) {
// do nothing... just hold your breath.
}
// bit is cleared, so we have a result.

// read from the ADCL/ADCH registers, and combine the result
// Note: ADCL must be read first (datasheet pp. 259)
uint16_t result = ADCL;
uint16_t temp = ADCH;
result = result + (temp<<8);

// set ADSC bit to get the *next* conversion started
ADCSRA |= (1<<ADSC);

return result;
}

double sampleToFahrenheit(uint16_t sample) {
// conversion ratio in DEGREES/STEP:
// (5000 mV / 1024 steps) * (1 degree / 10mV)
//  ^^^^^^^^^^^      ^^^^^^^^^^
//     from ADC       from LM34
return sample * (5000.0 / 1024.0 / 10.0);  
}

int main() {
// start up the LCD
//lcd_init();
//FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);
//lcd_home();

// start up the Analog to Digital Converter
adc_init();

// start up the serial port
 uart_init();
 FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
 stdin = stdout = &uart_stream;

int data_inp_1;

  // holder variables for temperature data
 uint16_t last_sample = 0;
double this_temp;
double temp_avg;
uint8_t i;

while(1) {
// take 100 samples and average them!
ADMUX = 0;
temp_avg = 0.0;
for(i=0; i<100; i++) {
  last_sample = adc_read();
  this_temp = sampleToFahrenheit(last_sample);

  // add this contribution to the average
  temp_avg = temp_avg + this_temp/100.0;
}

if (temp_avg > data_inp_1 ){ //|| temp_avg < 85){

  // LED as output
  DDRB |= (1<<PB4);

  // turn on LED
  PORTB |= (1<<PB4);

 } else {

 // turn off LED
 PORTB &= ~(1<<PB4);
  }

// write message to LCD
//lcd_home();
//lcd_write_string(PSTR("ADC: "));
//lcd_write_int16(last_sample);
//lcd_write_string(PSTR(" of 1024   "));
//lcd_line_two();
//fprintf_P(&lcd_stream, PSTR("Temperature: %.2f"), (temp_avg-32)*.5556);
//lcd_write_data(0xdf);
//lcd_write_string(PSTR("C      "));

// write message to serial port
 printf_P(PSTR("%.2f degrees F\r\n"), temp_avg);
 scanf_P(PSTR("%d"), &data_inp_1);
 }

return 0;
 }
May 05, 2011
by hevans
(NerdKits Staff)

hevans's Avatar

Hi kemil,

scanf is a blocking I/O call. Which means the code will wait to read something before moving on. This is probably what is causing your confusion. What you can probably do is use the uart_char_is_waiting() function of uart.c to check if there is anything waiting on the serial port, and only call scanf if there is something to read.

Humberto

May 09, 2011
by kemil
kemil's Avatar

Thanks Humberto,

That Solved one of the problems but now i have another! As previously mentioned i want to be able to send commands to the mcu whilst at the same time get temp readings from it. The thing is i cant seem to get a continuous stream of data from it unless i use an infinate while loop and it seems that if i do that i can no change the temperature range(i have a little function which just turns on an LED if i the temperature is above a certain value which i can adjust through my small gui). I need to be able to continuously read the serial data whilst doing other things.

Thanks Kemil

Here's my python code:

import threading
import serial
import time
from Tkinter import *
from Dialog import Dialog

root = Tk()
root.title("Temp Entry box")
enter_data_1 = Entry(root, bg = "pale green")
enter_data_1.grid(row=1, column=1)
enter_data_1.insert(0,"enter text here")
ser =  serial.Serial("COM4", 115200, timeout=1)   
#class FeederThread(threading.Thread): 
 # def run(self):
def callback_origin():
    #while 1:
      data_inp_1 = enter_data_1.get()
      label_2_far_right = Label(root, text=data_inp_1)
      label_2_far_right.grid(row=1, column = 3)

      ser.write(str(int(data_inp_1)))
      ser.write("\n")
      prevVal = None

      # Read the serial value

      ser.flushInput()
      serialValue = ser.readline().strip()
      # Catch any bad serial data:
      try:
         if serialValue != prevVal:
            # Print the value if it differs from the prevVal:
            print "New Val: ", serialValue
            prevVal = serialValue
      except ValueError:
         pass

but1= Button(root, text="press to transfer", /
command=callback_origin).grid(row=5,column=0)
root.mainloop()

Post a Reply

Please log in to post a reply.

Did you know that using an alternating excitation voltage can reduce the noise in many sensor measurements? Learn more...