Sei sulla pagina 1di 10

4/28/2015

justincase:PlottinglivedatafromMSP430ADCinPython
2

More NextBlog

CreateBlog SignIn

justincase

,152014.

Plotting live data from MSP430 ADC in


Python
:c,english,hardware,launchpad,matplotlib,msp430,programming,pyserial,python,serial,
temperature,uart

I'vefinallygotsomethingforpost.
LastmonthI'vebeenplayingwiththeTIMSP430
LaunchpadandwhenIworkwithADCitlacksof
visualization.SinceLaunchpadhaveUARTUSB
interface,Idecidedtoplotincomingdata.
I'musingMSP430G2553,andallcodewaswritten
forthiscontroller.
Firmware

Firmwareofcontrollerisprettystraightforwardin
largescale:itjustsendsvaluefromADCtotheUARTcontinouslywithonenote:before
starttosendanything,weneedtomakea"handshake"receivestartsymbolfrom
computer.So,highlevelalgorithmwillbelikethis:
1)InitializeUART[1](9600baud)andADC[2]
2)Waitforstartsignal("handshake")
3)InforeverloopsendtemperaturetoUART
ADCinitializationtoreadtemperature(10channel):
voidADC_init(void){
ADC10CTL0=SREF_1+REFON+ADC10ON+ADC10SHT_3
ADC10CTL1=INCH_10+ADC10DIV_3
}
intgetTemperatureCelsius()
{
intt=0
__delay_cycles(1000)//Notneccessary.
ADC10CTL0|=ENC+ADC10SC
while(ADC10CTL1&BUSY)
t=ADC10MEM
ADC10CTL0&=~ENC
return(int)((t*27069L18169625L)>>16)//magic
conversiontoCelsius
}
http://antigluk.blogspot.in/2014/07/plottinglivedatafrommsp430adcin.html

1/10

4/28/2015

justincase:PlottinglivedatafromMSP430ADCinPython

Handshake:
//UARTHandshake...
unsignedcharc
while((c=uart_getc())!='1')
uart_puts((char*)"\nOK\n")
We'rewaitingfor'1'andsending"OK"whenwereceiveit.
Afterthat,programstartstosendtemperatureindefinitely:

while(1){
uart_printf("%i\n",getTemperatureCelsius())
P1OUT^=0x1
}
uart_printfconvertsintegervalueintostringandsendoverUART
[3].
Thesourcecodeoffirmwareinthebottomofthispost.
PlottingApplication

Ilovematplotlibinpython,it'sgreatlibrarytoploteverything.ToreaddatafromUART,I
usedpySeriallibrary.That'sallweneed.
Whenweconnectlaunchpadtocomputer,device/dev/ttyACM0iscreated.It'sserialport
whichweneedtouse.
Applicationconsistsoftwothreads:
1. Serialportprocessing
2. Continousplotupdating

Serialportprocessing
Let'sdefineglobalvariabledata=deque(0for_inrange(5000)),itwillcontain
datatoplotanddataP=deque(0for_inrange(5000)),itwillcontain
approximatedvalues.
Intheserialportthread,weneedtoopenconnection:
ser=serial.Serial('/dev/ttyACM0',9600,timeout=1)
then,makea"handshake":
ok=b''
whileok.strip()!=b'OK':
ser.write(b"1")
ok=ser.readline()
print("HandshakeOK!\n")
Asyousee,we'rewaitingthe"OK"inresponseto"1".After"handshake",wecanstart
readingdata:
http://antigluk.blogspot.in/2014/07/plottinglivedatafrommsp430adcin.html

2/10

4/28/2015

justincase:PlottinglivedatafromMSP430ADCinPython

whileTrue:
try:
val=int(ser.readline().strip())
addValue(val)
exceptValueError:
pass
UARTisnotverystable,sosometimesyoucanreceivedistorteddata.That'swhyIeat
exceptions.
addValuehereisfunctionthatprocessesdataandputsittodatavariable:
avg=0
defaddValue(val):
globalavg
data.append(val)
data.popleft()

avg=avg+0.1*(valavg)
dataP.append(avg)
dataP.popleft()
Alsoitcalculatesweightedmovingaverage:

Continousplotupdating
First,let'screatefigurewithtwoplots:
fig,(p1,p2)=plt.subplots(2,1)
plot_data,=p1.plot(data,animated=True)
plot_processed,=p2.plot(data,animated=True)
p1.set_ylim(0,100)#ylimits
p2.set_ylim(0,100)
Todrawanimatedplot,weneedtodefinefunctionthatwillupdatedata:
defanimate(i):
plot_data.set_ydata(data)
plot_data.set_xdata(range(len(data)))
plot_processed.set_ydata(dataP)
plot_processed.set_xdata(range(len(dataP)))
return[plot_data,plot_processed]
ani=animation.FuncAnimation(fig,animate,range(10000),
interval=50,blit=True)
http://antigluk.blogspot.in/2014/07/plottinglivedatafrommsp430adcin.html

3/10

4/28/2015

justincase:PlottinglivedatafromMSP430ADCinPython

Andshowtheplotwindow:
plt.show()
Here'stheresultofprogram'swork:

Onthefirstplotit'srawdatareceivedthroughserialport,onthesecondit'saverage.
Sourcecodes

Desktopliveplottingapplication:

1 importmatplotlib.pyplotasplt
2 importmatplotlib.animationasanimation
3 importserial
4 importthreading
5 fromcollectionsimportdeque
6
7 data=deque(0for_inrange(5000))
8 dataP=deque(0for_inrange(5000))
9 avg=0
10
11 defaddValue(val):
12 globalavg
13
14 data.append(val)
15 data.popleft()
16
17 avg=avg+0.1*(valavg)
18 dataP.append(avg)
19 dataP.popleft()
20
21
22 defmsp430():
23 print("Connecting...")
24 ser=serial.Serial('/dev/ttyACM0',9600,timeout=1)
25 print("Connected!")
26
27 #Handshake...
28 ok=b''
29 whileok.strip()!=b'OK':
30 ser.write(b"1")
31 ok=ser.readline()
http://antigluk.blogspot.in/2014/07/plottinglivedatafrommsp430adcin.html

4/10

4/28/2015

justincase:PlottinglivedatafromMSP430ADCinPython

32 print(ok.strip())
33 print("HandshakeOK!\n")
34
35 whileTrue:
36 try:
37 val=int(ser.readline().strip())
38 addValue(val)
39 print(val)
40 exceptValueError:
41 pass
42
43
44 if__name__=="__main__":
45 threading.Thread(target=msp430).start()
46
47 fig,(p1,p2)=plt.subplots(2,1)
48 plot_data,=p1.plot(data,animated=True)
49 plot_processed,=p2.plot(data,animated=True)
50 p1.set_ylim(0,100)
51 p2.set_ylim(0,100)
52 defanimate(i):
53 plot_data.set_ydata(data)
54 plot_data.set_xdata(range(len(data)))
55 plot_processed.set_ydata(dataP)
56 plot_processed.set_xdata(range(len(dataP)))
57 return[plot_data,plot_processed]
58
59 ani=animation.FuncAnimation(fig,animate,range(10000),
60 interval=50,blit=True)
61 plt.show()

MSP430fullfirmware:

1 /*
2 NOTICE
3 Usedcodeorgotanideafrom:
4 UART:StefanWendlerhttp://gpio.kaltpost.de/?page_id=972
5 ADC:http://indiantinker.wordpress.com/2012/12/13/tutorialusingtheinternal
6 printf:http://forum.43oh.com/topic/1289tinyprintfcversion/
7 */
8
9 #include<msp430g2553.h>
10
11 //===========HEADERS===============
12 //UART
13 voiduart_init(void);
14 voiduart_set_rx_isr_ptr(void(*isr_ptr)(unsignedcharc));
15 unsignedcharuart_getc();
16 voiduart_putc(unsignedcharc);
17 voiduart_puts(constchar*str);
18 voiduart_printf(char*,...);
19 //ADC
20 voidADC_init(void);
21 //===========/HEADERS===============
22
http://antigluk.blogspot.in/2014/07/plottinglivedatafrommsp430adcin.html

5/10

4/28/2015

justincase:PlottinglivedatafromMSP430ADCinPython

23
24 //Triggeronreceivedcharacter
25 voiduart_rx_isr(unsignedcharc){
26 P1OUT^=0x40;
27 }
28
29 intmain(void)
30 {
31 WDTCTL=WDTPW+WDTHOLD;
32
33 BCSCTL1=CALBC1_8MHZ;//SetDCOto8Mhz
34 DCOCTL=CALDCO_8MHZ;//SetDCOto8Mhz
35
36 P1DIR=0xff;
37 P1OUT=0x1;
38 ADC_init();
39 uart_init();
40 uart_set_rx_isr_ptr(uart_rx_isr);
41
42 __bis_SR_register(GIE);//globalinterruptenable
43
44 //UARTHandshake...
45 unsignedcharc;
46 while((c=uart_getc())!='1');
47 uart_puts((char*)"\nOK\n");
48
49 ADC10CTL0|=ADC10SC;
50 while(1){
51 uart_printf("%i\n",getTemperatureCelsius());
52 P1OUT^=0x1;
53 }
54 }
55
56 //========================================================
57 //ADCconfiguredtoreadtemperature
58 voidADC_init(void){
59 ADC10CTL0=SREF_1+REFON+ADC10ON+ADC10SHT_3;
60 ADC10CTL1=INCH_10+ADC10DIV_3;
61 }
62
63 intgetTemperatureCelsius()
64 {
65 intt=0;
66 __delay_cycles(1000);
67 ADC10CTL0|=ENC+ADC10SC;
68 while(ADC10CTL1&BUSY);
69 t=ADC10MEM;
70 ADC10CTL0&=~ENC;
71 return(int)((t*27069L18169625L)>>16);
72 }
73
74
75 //========================================================
76 //UART
77 #include<legacymsp430.h>
78
79 #defineRXDBIT1
80 #defineTXDBIT2
http://antigluk.blogspot.in/2014/07/plottinglivedatafrommsp430adcin.html

6/10

4/28/2015

justincase:PlottinglivedatafromMSP430ADCinPython

81
82 /**
83 *Callbackhandlerforreceive
84 */
85 void(*uart_rx_isr_ptr)(unsignedcharc);
86
87 voiduart_init(void)
88 {
89 uart_set_rx_isr_ptr(0L);
90
91 P1SEL=RXD+TXD;
92 P1SEL2=RXD+TXD;
93
94 UCA0CTL1|=UCSSEL_2;//SMCLK
95 //8,000,000Hz,9600Baud,UCBRx=52,UCBRSx=0,UCBRFx=1
96 UCA0BR0=52;//8MHz,OSC16,9600
97 UCA0BR1=0;//((8MHz/9600)/16)=52.08333
98 UCA0MCTL=0x10|UCOS16;//UCBRFx=1,UCBRSx=0,UCOS16=1
99 UCA0CTL1&=~UCSWRST;//USCIstatemachine
100 IE2|=UCA0RXIE;//EnableUSCI_A0RXinterrupt
101 }
102
103 voiduart_set_rx_isr_ptr(void(*isr_ptr)(unsignedcharc))
104 {
105 uart_rx_isr_ptr=isr_ptr;
106 }
107
108 unsignedcharuart_getc()
109 {
110 while(!(IFG2&UCA0RXIFG));//USCI_A0RXbufferready?
111 returnUCA0RXBUF;
112 }
113
114 voiduart_putc(unsignedcharc)
115 {
116 while(!(IFG2&UCA0TXIFG));//USCI_A0TXbufferready?
117 UCA0TXBUF=c;//TX
118 }
119
120 voiduart_puts(constchar*str)
121 {
122 while(*str)uart_putc(*str++);
123 }
124
125 interrupt(USCIAB0RX_VECTOR)USCI0RX_ISR(void)
126 {
127 if(uart_rx_isr_ptr!=0L){
128 (uart_rx_isr_ptr)(UCA0RXBUF);
129 }
130 }
131
132
133
134 //========================================================
135 //UARTPRINTF
136 #include"stdarg.h"
137
138 staticconstunsignedlongdv[]={
http://antigluk.blogspot.in/2014/07/plottinglivedatafrommsp430adcin.html

7/10

4/28/2015

justincase:PlottinglivedatafromMSP430ADCinPython

139 //4294967296//32bitunsignedmax
140 1000000000,//+0
141 100000000,//+1
142 10000000,//+2
143 1000000,//+3
144 100000,//+4
145 //65535//16bitunsignedmax
146 10000,//+5
147 1000,//+6
148 100,//+7
149 10,//+8
150 1,//+9
151 };
152
153 staticvoidxtoa(unsignedlongx,constunsignedlong*dp)
154 {
155 charc;
156 unsignedlongd;
157 if(x){
158 while(x<*dp)++dp;
159 do{
160 d=*dp++;
161 c='0';
162 while(x>=d)++c,x=d;
163 uart_putc(c);
164 }while(!(d&1));
165 }else
166 uart_putc('0');
167 }
168
169 staticvoidputh(unsignedn)
170 {
171 staticconstcharhex[16]={'0','1','2','3','4','5','6','7','8',
172 uart_putc(hex[n&15]);
173 }
174
175 voiduart_printf(char*format,...)
176 {
177 charc;
178 inti;
179 longn;
180
181 va_lista;
182 va_start(a,format);
183 while(c=*format++){
184 if(c=='%'){
185 switch(c=*format++){
186 case's'://String
187 uart_puts(va_arg(a,char*));
188 break;
189 case'c'://Char
190 uart_putc(va_arg(a,char));
191 break;
192 case'i'://16bitInteger
193 case'u'://16bitUnsigned
194 i=va_arg(a,int);
195 if(c=='i'&&i<0)i=i,uart_putc('');
196 xtoa((unsigned)i,dv+5);
http://antigluk.blogspot.in/2014/07/plottinglivedatafrommsp430adcin.html

8/10

4/28/2015

justincase:PlottinglivedatafromMSP430ADCinPython

197 break;
198 case'l'://32bitLong
199 case'n'://32bituNsignedloNg
200 n=va_arg(a,long);
201 if(c=='l'&&n<0)n=n,uart_putc('');
202 xtoa((unsignedlong)n,dv);
203 break;
204 case'x'://16bitheXadecimal
205 i=va_arg(a,int);
206 puth(i>>12);
207 puth(i>>8);
208 puth(i>>4);
209 puth(i);
210 break;
211 case0:return;
212 default:gotobad_fmt;
213 }
214 }else
215 bad_fmt:uart_putc(c);
216 }
217 va_end(a);
218 }

Sources
[1]UART:StefanWendlerhttp://gpio.kaltpost.de/?page_id=972
[2]ADC:http://indiantinker.wordpress.com/2012/12/13/tutorialusingthe
internaltemperaturesensoronamsp430/
[3]printf:http://forum.43oh.com/topic/1289tinyprintfcversion/

+2 Google

...

Google

:(Atom)

http://antigluk.blogspot.in/2014/07/plottinglivedatafrommsp430adcin.html

9/10

4/28/2015

justincase:PlottinglivedatafromMSP430ADCinPython

RomanRader

http://antigluk.blogspot.in/2014/07/plottinglivedatafrommsp430adcin.html

10/10

Potrebbero piacerti anche