I am Italian and, despite the fact that I am not living anymore in Italy since few years, when Italy has to renew the government, I still vote there.
Since,after I left my country, I don't have many opportunities to meet in person with my old friends, I often used to debate with them through social media (not now, I closed my fb account)
At the last political elections, back in 2008, among my friends we were pretty convinced that Berlusconi had no chance to win.
But then the polls already had different predictions and finally, he definitely won.
The problem is that when you meet with people in real life, you tend to aggregate with those having similar interests, probably with a similar level of instruction and potentially with similar political views.
However in real life you simply MEET people of different kind.
You may not necessarily try to meet and discuss with someone, but simply as you walk down the street you need to interact with "others".
With social media it is different, you don't HAVE to bump into whoever, you CHOSE to.
If this sounds "cool" on one side, it has some serious side effects.
I believe you end up getting an illusive picture of the world, it's probably a world that resembles a lot what you already had in mind, so it gets addictive.
It is something that "proves you right" and, let's face it, we all like that.
However it fails badly in being "culturally challenging" which, I personally believe, is one of the main drivers for our cultural evolution.
My point is : social media are products, as such they need to generate profits.
In order to generate profits they need to sell and to sell they must please their customers.
What pleases you more than being surrounded by people you know, that shares your habits, interests, views...
We are fundamentally "lazy" and we normally feel at ease when others confirm our opinions, it means we do not need to over-think, to challenge them.
But in the end, is it good for us?
I have a small youtube channel and I just checked the stats :
the vast majority of the viewers are males between 35 and 44 years, just like I am.
Is there a new way of designing social media to stimulate an honest, open debate, to challenge our beliefs and at the same time being attractive to us?
Search Microcontrollers
Friday, September 21, 2012
Thursday, September 20, 2012
Some mice are smarter
I have two cats and I live in the countryside.
Their favorite sport is napping, but their second favorite one is chasing mice.
We have plenty of them here, they are little funny animals, and I try to save them when I can.
Lately my two furry hunters got the habit of scouting the area around the house, catch a mouse and then run back in the house with him to play, normally in my studio.
They really like me to participate to this game, especially around 3am, in that case they normally elect my bedroom as "chasing arena".
Yesterday I was discussing over the phone with a customer and one of the cats arrived running with a mouse in her mouth, she freed him under my desk and started the chase.
I recon this little fellow could be the one I already saved a couple of days ago, so he is already familiar with the environment.
I imagine him thinking "oh God... here we go again...".
He knew already that hiding behind my computer normally works, so he headed straight there while the cat was guarding the area and waiting for him to pop out.
But when they survive, they probably get smarter, so this one decided to take his revenge.
He climbed on top of my desk and eventually got to the little bag of cat treats that I keep there.
This is what happened
In the end he did not manage to open the bag, but I thought he deserved some treats, so I opened it and tossed a couple to him.
Their favorite sport is napping, but their second favorite one is chasing mice.
We have plenty of them here, they are little funny animals, and I try to save them when I can.
Lately my two furry hunters got the habit of scouting the area around the house, catch a mouse and then run back in the house with him to play, normally in my studio.
They really like me to participate to this game, especially around 3am, in that case they normally elect my bedroom as "chasing arena".
Yesterday I was discussing over the phone with a customer and one of the cats arrived running with a mouse in her mouth, she freed him under my desk and started the chase.
I recon this little fellow could be the one I already saved a couple of days ago, so he is already familiar with the environment.
I imagine him thinking "oh God... here we go again...".
He knew already that hiding behind my computer normally works, so he headed straight there while the cat was guarding the area and waiting for him to pop out.
But when they survive, they probably get smarter, so this one decided to take his revenge.
He climbed on top of my desk and eventually got to the little bag of cat treats that I keep there.
This is what happened
In the end he did not manage to open the bag, but I thought he deserved some treats, so I opened it and tossed a couple to him.
Monday, September 17, 2012
MSP430G2 & Wifly - The internet of things
In the previous two posts I explained how to interface an RN XV wifly module with a Launchpad (MSP430G2553).
In the last post I discussed an easier method that can be used to connect to a remote webserver (or any TCP based service), and today I will implement it with the Launchpad.
First thing I created a simple php page, named pp.php which looks something like this :
<?
// connect to databse
//...
// get $mn and $mv from the request
// ...
$sql = "insert into test (tstamp,measureName,measureValue) values (now(),'".$mn."',".$mv.")";
// execute query
echo "[[[[ok]]]]";
?>
this page inserts a record into a mysql table called "test".
Suppose my server is http://www,myserver.com, to test the page we need to open a browser and call :
Using the technique illustrated in the previous post, I stored the server address into the wifly configuration :
set ip proto 18
set dns name www.myserver.com
set ip address 0
set ip remote 80
set com remote 0
save
reboot
We will use the wifly gpio lines 4,5 and 6 to detect if the module is associated with a ssid, then to ask it to connect with the TCP address stored in the config and once gpio6 is high (tcp connected) we will send the get command via uart.
I connected the pins 2.0, 2.1,2.2 on the launchpad respectively to gpio4,gpio6,gpio5 on the wifly
P2.0 -> gpio4 (associated) - input
P2.1 -> gpio6 (connected) - input
P2.2 -> gpio5 (connect) - output
Let's configure the P2 port on the launchpad :
void configGpio()
{
P2DIR |=BIT2; // P2.2 output
// P2.2 is connected to wifly gpio5
P2DIR &= ~(BIT0 + BIT1); // P2.0 and P2.1 input
// P2.0 is connected to wifly gpio4
// P2.1 is connected to wifly gpio6
P2REN |=BIT0 + BIT1;
// pulldown resistors
P2OUT &= ~(BIT2);
}
Then we need a procedure to send the GET request.
In my case I had to use HTTP/1.1 specifications and chances are that you will have to do the same unless you are working with you local webserver.
The GET command for version 1.1 of the HTTP protocol requires that the Host is always specified at each request, so the GET is someting like :
GET /pp.php?mn=wifly&mv=123.45 HTTP/1.1
Host: www.myserver.com
And this is the procedure I use
void wifly_TCPsend(char *text)
{
if ((P2IN & BIT0)>0) // wifly is associated
{
if ((P2IN & BIT1)>0) // wifly is connected
{
UART_TX(text);
__delay_cycles(16000000); //wait 1 second
P2OUT &= ~BIT2; // close connection
__delay_cycles(16000000); //wait 1 second
wifly_enterCommandMode();
UART_TX("sleep\0");
__delay_cycles(160000000); //wait 10 seconds
} else
// associated, but not connected -> let's connect
P2OUT |= BIT2; // pulls wifly gpio5 high
} else
{ // the module is not associated
wifly_enterCommandMode();
UART_TX("join\0");
__delay_cycles(16000000); //wait 1 second
}
This implementation is pretty basic, it works this way :
1) we check if the module is associated to a ssid, if not we try to send a join command. It should not be needed as we pre-configured the module to automatically join the stored ssid
2) Once the module is associated (gpio4 -P2.0- is high) we raise gpio5 (P2.2) to initiate a tcp connection
3) Once the connection has been successfully established, the gpio6 (2.1) goes high and we can send the get request via uart
The main procedure becomes :
void main(void)
{ // stop the watchdog
WDTCTL = WDTPW + WDTHOLD; // allow debugging
configClock();
configUART();
configGpio();
while (1)
{
// do whatever you need here, like getting values from the ADC
// or reading sensors via SPI or I2C...
// then customize the get call according to your needs
wifly_TCPsend("GET /pp.php?m=wifly&v=123.45 HTTP/1.1\nHost: www.myserver.com\n\0");
// you may want to place this in an interrupt timer routine and sleep while waiting
}
}
One tricky issue is to actually read data from the webserver.
Data is coming back, no issues with that, but the server will send you also some header information, which will force you to parse the content.
Again, parsing a text is no the best thing to do with a device with minim memory, so you may want to use some kind of TAG to identify the only part of text that should be considered.
My php webpage uses
to pass back the "ok" message, so, the launchpad will disregard the incoming uart data until a series of four consecutive "[" are received.
In the last post I discussed an easier method that can be used to connect to a remote webserver (or any TCP based service), and today I will implement it with the Launchpad.
First thing I created a simple php page, named pp.php which looks something like this :
<?
// connect to databse
//...
// get $mn and $mv from the request
// ...
$sql = "insert into test (tstamp,measureName,measureValue) values (now(),'".$mn."',".$mv.")";
// execute query
echo "[[[[ok]]]]";
?>
this page inserts a record into a mysql table called "test".
Suppose my server is http://www,myserver.com, to test the page we need to open a browser and call :
http://www,myserver.com/pp.php?mn=wifly&mv=2.32
Using the technique illustrated in the previous post, I stored the server address into the wifly configuration :
set ip proto 18
set dns name www.myserver.com
set ip address 0
set ip remote 80
set com remote 0
save
reboot
We will use the wifly gpio lines 4,5 and 6 to detect if the module is associated with a ssid, then to ask it to connect with the TCP address stored in the config and once gpio6 is high (tcp connected) we will send the get command via uart.
I connected the pins 2.0, 2.1,2.2 on the launchpad respectively to gpio4,gpio6,gpio5 on the wifly
P2.0 -> gpio4 (associated) - input
P2.1 -> gpio6 (connected) - input
P2.2 -> gpio5 (connect) - output
Let's configure the P2 port on the launchpad :
void configGpio()
{
P2DIR |=BIT2; // P2.2 output
// P2.2 is connected to wifly gpio5
P2DIR &= ~(BIT0 + BIT1); // P2.0 and P2.1 input
// P2.0 is connected to wifly gpio4
// P2.1 is connected to wifly gpio6
P2REN |=BIT0 + BIT1;
// pulldown resistors
P2OUT &= ~(BIT2);
}
Then we need a procedure to send the GET request.
In my case I had to use HTTP/1.1 specifications and chances are that you will have to do the same unless you are working with you local webserver.
The GET command for version 1.1 of the HTTP protocol requires that the Host is always specified at each request, so the GET is someting like :
GET /pp.php?mn=wifly&mv=123.45 HTTP/1.1
Host: www.myserver.com
And this is the procedure I use
void wifly_TCPsend(char *text)
{
if ((P2IN & BIT0)>0) // wifly is associated
{
if ((P2IN & BIT1)>0) // wifly is connected
{
UART_TX(text);
__delay_cycles(16000000); //wait 1 second
P2OUT &= ~BIT2; // close connection
__delay_cycles(16000000); //wait 1 second
wifly_enterCommandMode();
UART_TX("sleep\0");
__delay_cycles(160000000); //wait 10 seconds
} else
// associated, but not connected -> let's connect
P2OUT |= BIT2; // pulls wifly gpio5 high
} else
{ // the module is not associated
wifly_enterCommandMode();
UART_TX("join\0");
__delay_cycles(16000000); //wait 1 second
}
}
This implementation is pretty basic, it works this way :
1) we check if the module is associated to a ssid, if not we try to send a join command. It should not be needed as we pre-configured the module to automatically join the stored ssid
2) Once the module is associated (gpio4 -P2.0- is high) we raise gpio5 (P2.2) to initiate a tcp connection
3) Once the connection has been successfully established, the gpio6 (2.1) goes high and we can send the get request via uart
The main procedure becomes :
void main(void)
{ // stop the watchdog
WDTCTL = WDTPW + WDTHOLD; // allow debugging
configClock();
configUART();
configGpio();
while (1)
{
// do whatever you need here, like getting values from the ADC
// or reading sensors via SPI or I2C...
// then customize the get call according to your needs
wifly_TCPsend("GET /pp.php?m=wifly&v=123.45 HTTP/1.1\nHost: www.myserver.com\n\0");
// you may want to place this in an interrupt timer routine and sleep while waiting
}
}
.. and sue enough I have the values logged in my mysql table in my remote webserver.
One tricky issue is to actually read data from the webserver.
Data is coming back, no issues with that, but the server will send you also some header information, which will force you to parse the content.
Again, parsing a text is no the best thing to do with a device with minim memory, so you may want to use some kind of TAG to identify the only part of text that should be considered.
My php webpage uses
echo "[[[[ok]]]]";
to pass back the "ok" message, so, the launchpad will disregard the incoming uart data until a series of four consecutive "[" are received.
Why would we want to pass data back to the launchpad?
Imagine you store in your webserver the configuration to manage the heating system of your Chalet.
When you decide it's a good weekend to go there, you may want to turn the heating on (or increase the temperature) few hours before, then to turn it off automatically at the end of the weekend.
Your launchpad, installed in your chalet, will read the current temperature (it has a temp sensor inside), every minute it will check with your webserver what it has to do with that temperature.
The webserver will check and will send back a "ON" or "OFF" response.
There are plenty of possible implementations, let me know your ideas!
Friday, September 14, 2012
Roving Networks RN XV - Wifly module
In the previous post I illustrated a basic way to interface the wifly module to the MSP430G2 using the uart.
As I already anticipated in that post, the method could be improved, but for that we need to dig in a bit into the features of this module.
The wifly has the ability to store configurations, this means that we can pre-set all the needed parameters and we can avoid to send them from the mcu via uart.
Using an FTDI cable I connect to the module and set the config pars :
$$$ (to enter in command mode)
set wlan auth 3
set wlan ssid myssid
set wlan phrase mypwd
set wlan channel 0 (0 means autoscan)
save
The configuration is now saved and it will be automatically loaded at each reboot / power up.
Once these parameters are set, to join the ssid, we will just need to issue the command
join
However we could even do better than that, in fact, if we set the auto join function to "1" (which btw is the default) the wifly will automatically try to join the ssid at each reboot.
set wlan join 1
save
Cool, not much to do for our mcu now, eh?
Just wait, it actually gets even better.
Fine, we are associated with the ssid, we got an ip address etc, now we need to establish a tcp connection to a remote server.
I quote from the RN XV user manual :
set ip proto 18 //enable html client
set dns name www.webserver.com //name of your webserver
set ip address 0 // so WiFly will use DNS
set ip remote 80 // standard webserver port
set com remote 0 // turn off the REMOTE string so it does not interfere with the post
You guessed that, you can save this too in the internal config!
save
To make the connection the command would be:
open
or inline you can send open www.webserver.com 80
The user’s microprocessor should write to the uart:
GET /ob.php?obvar=WEATHER \n\n
So, finally this makes things way easier, but it's not the end of the story...
What if we could check from a gpio pin if the wifly is associated, then raise another gpio to ask it to connect to the remote tcp port and finally get from a third gpio if it successfully connected?
Yup, that's another nice feature which is actually available.
The specific gpio pins are the 4,5 and 6 and must be configured to be used in this way.
set sys iofunc 0x70 // enable alternate function for GPIO 6, 5 and 4
save
With all this set and saved in the configuration, at power on the wifly module will try to associate to the ssid. once it is ready to perform a tcp connection it will raise gpio4 (which we will check from our mcu).
At that point, when we need to contact the remote server, we will raise the gpio5 and check gpio6 to verify that the connection was established.
At that point, if we are contacting a web server, we will send the GET request through the uart and will receive the answer from there.
... and we did not even need to enter in command mode!
Nice eh?
Will implement this with the launchpad in the next days.
As I already anticipated in that post, the method could be improved, but for that we need to dig in a bit into the features of this module.
The wifly has the ability to store configurations, this means that we can pre-set all the needed parameters and we can avoid to send them from the mcu via uart.
Using an FTDI cable I connect to the module and set the config pars :
$$$ (to enter in command mode)
set wlan auth 3
set wlan ssid myssid
set wlan phrase mypwd
set wlan channel 0 (0 means autoscan)
save
The configuration is now saved and it will be automatically loaded at each reboot / power up.
Once these parameters are set, to join the ssid, we will just need to issue the command
join
However we could even do better than that, in fact, if we set the auto join function to "1" (which btw is the default) the wifly will automatically try to join the ssid at each reboot.
set wlan join 1
save
Cool, not much to do for our mcu now, eh?
Just wait, it actually gets even better.
Fine, we are associated with the ssid, we got an ip address etc, now we need to establish a tcp connection to a remote server.
I quote from the RN XV user manual :
set ip proto 18 //enable html client
set dns name www.webserver.com //name of your webserver
set ip address 0 // so WiFly will use DNS
set ip remote 80 // standard webserver port
set com remote 0 // turn off the REMOTE string so it does not interfere with the post
You guessed that, you can save this too in the internal config!
save
To make the connection the command would be:
open
or inline you can send open www.webserver.com 80
The user’s microprocessor should write to the uart:
GET /ob.php?obvar=WEATHER \n\n
So, finally this makes things way easier, but it's not the end of the story...
What if we could check from a gpio pin if the wifly is associated, then raise another gpio to ask it to connect to the remote tcp port and finally get from a third gpio if it successfully connected?
Yup, that's another nice feature which is actually available.
The specific gpio pins are the 4,5 and 6 and must be configured to be used in this way.
set sys iofunc 0x70 // enable alternate function for GPIO 6, 5 and 4
save
With all this set and saved in the configuration, at power on the wifly module will try to associate to the ssid. once it is ready to perform a tcp connection it will raise gpio4 (which we will check from our mcu).
At that point, when we need to contact the remote server, we will raise the gpio5 and check gpio6 to verify that the connection was established.
At that point, if we are contacting a web server, we will send the GET request through the uart and will receive the answer from there.
... and we did not even need to enter in command mode!
Nice eh?
Will implement this with the launchpad in the next days.
MSP430G2 - Interfacing a wifly (RN XV) module
Do you like "the internet of things" concept?
The RN XV, from Roving Networks is a versatile little device.
It is basically a wifi card with a serial port, designed to be easily connected to microcontrollers.
I previously used on my Arduino and even on my BeagleBone, where I used java (RXTX) to drive it.
I have a youtube video about the BeagleBone / wifly, but it's mainly about the Bone and RXTX than the RN XV, so I will not embed it here.
Did you ever work with old modems?
If so you are probably familiar with the Hayes protocol and the AT commands you sent over the serial port.
No, the RN XV does not use Hayes, but the concept is similar : you send commands in ASCII format to the serial port and in that way instruct the module to connect to a ssid, perform a http get etc.
The good thing about this is that it's easy to test the protocol just using an hyperterminal kind of software.
In windows I like to use Realterm, it's open source.
To connect the wifly to a PC you will need an FTDI usb interface (get yourself a couple of those from ebay if you don't have them already, they are extremely handy).
To easily work with the RN XV (other compatible modules might be slightly different in this regard, so check carefully your specific case) you will also need (or "you will be better of with") a breakout board for it. (it is cheap, no worries).
The reason you may want the breakout board is that the pin pitch of the RN XV is designed to match the XBee standard, which would not work with the common headers you normally use.
Final consideration : the wifly modules work at 3.3V which makes them perfect to work with the MSP430G2, should you use an AVR or other MCUs, make sure the serial communication runs ar 3.3V, else you need a logic level converter.
Let's connect the RN XV with the Launchpad :
In my example I am powering the wifly module from the Launchpad, the 3,3V is taken from pin 1 on the lp.
Besides Vcc and GND for now we will just need the UART rx and tx signals.
You may wonder why the wifly has so many pins.
Like Dave would say : "I am glad you asked!".
The Roving Networks wifi interface contains an MCU which obviously has GPIO and other features (including an ADC which I never tried so far, but it promises 14 bit resolution !!!).
The functionality of the contained mcu are accessible through the various pins, we will probably need to use some of those later on.
As a general consideration, a text based protocol is normally handy to implement an interface, it makes it easier to debug and it's normally quite flexible.
Unfortunately it may become difficult to manage if the amount of RAM you have at your disposal is limited, like in the case of the MSP430G2.
We then need to design the handling routines accordingly, we will not be able to allocate a big buffer to store incoming data to be processed asynchronously.
In general a synchronous approach would probably reduce the amount of needed memory and it could eventually work with the wifly protocol, however I am going for a simple asynchronous implementation, using the uart interrupt on the MSP430G2, just to make sure we do not miss any incoming char.
By default, the wifly uart starts at 9600 baud, 8 N 1.
Let's start configuring the clock and uart on the launchpad (details here) :
#include <msp430g2553.h>
// configure the CPU clock (MCLK)
// to run from DCO @ 16MHz and SMCLK = DCO / 4
void configClock()
{
BCSCTL1 = CALBC1_16MHZ; // Set DCO
DCOCTL = CALDCO_16MHZ;
BCSCTL2= DIVS_2 + DIVM_0; // divider=4 for SMCLK and 1 for MCLK
}
void configUART()
{
// set the pin mode 3 for pins 1 & 2 of port 1 (Uart mode)
P1SEL |= BIT1 + BIT2; // low bit = 1 for pin 1 and 2
P1SEL2 |= BIT1 + BIT2; // high bit = 1 for pin 1 and 2
// configure the UART
UCA0CTL0 = 0; //UART mode, No parity, LSB first, 8 data, 1 stop
UCA0CTL1 = UCSSEL_2; //use SCLK
UCA0BR0 = 0x1A; //lower byte of UCBR0. 26dec
//(4MHz / 9600 baud) see table 15-5
UCA0BR1 = 0x0; //upper byte of UCBR0.set to 0
UCA0MCTL = UCBRF_1 + UCBRS_0 + UCOS16; //sets UCBRFx to 1,
// UCBRSx tto 0 , UCOS16=1
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI **
UC0IE |= UCA0RXIE; // Enable USCI_A1 RX interrupt
_EINT(); // global enable interrupts
}
Together with the buffer I declare a buffer pointer, now, there are different ways to manage a buffer, I am going for a "circular management" approach which is quite common in these situations.
The receiving (interrupt) routine will store the incoming char in UART_buffer[bufPtr] and then increment bufPtr, when the end of the buffer is reached, since bufPtr is a byte (unsigned char) it will restart automatically from 0.
If we wanted a buffer size different from 256 we would have needed an if statement to check if the end of the buffer was reached and in that case reset the pointer.
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
char c = UCA0RXBUF;
if ((c!='\n')&&(c!='\r'))
UART_buffer[bufPtr++] = c;
else
if (c=='\r') wifly_process(bufPtr);
}
The command protocol of the wifly uses ASCII text responses terminated by CR LF (\r\n) so we will use that to acknowledge that a response has been received and needs to be processed.
While we process a text returned from the wifly, other chars could be incoming at the same time, therefore we need to pass the position of the end of the text to be processed in this iteration.
So, what's happening is that while we are filling the uart rx buffer, in parallel we have a procedure that at each CRLF received extracts a single response line.
The process procedure knows up to which char it has to process since this is passed by the interrupt routine, but if also needs to know from which char to START processing.
In the current implementation (it can be improved) I am copying a single returned line into a separate buffer that will be processed later on.
Also I added a flag to identify if there is a complete text line ready to be processed.
char wifly_rx[128];
unsigned char processPtr = 0;
unsigned char commComplete = 0;
void wifly_process(unsigned char i)
{
unsigned char cnt = 0;
while (processPtr!=i)
wifly_rx[cnt++] = UART_buffer[processPtr++];
wifly_rx[cnt] = '\0';
commComplete=1;
}
I am adding a char 0 at the end of the buffer as it is needed by the string handling routines I created.
The first (a bit painful) thing you have to know when working with the wifly protocol is that it has two functioning modes :
The data mode and the command mode.
To send commands you need to enter in the command mode (fair, no?) which, via the UART is achieved by sending three dollar isngs ( $$$ ) not followed by a crlf and wait for 250 ms.
That's fairly easy and the module will answer with "CMD".
Practically it's less obvious than you may think.
Firts, you may already be in command mode and in that case you will not get any answer until you send a crlf, second in some cases the module may not respond (it improved with the latest firmware releases).
A typical case is while establishing a connection to a ssid.
For this reason in the latest firmware releases an alternative method to enter in command mode, was implemented and it is based on pulses sent through the GPIO.
We will not implement that one right now.
void UART_SendChar(unsigned char txChar)
{
while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF=txChar;
}
void UART_TX(char *txStr)
{
unsigned int i=0;
while(txStr[i]!=0)
UART_SendChar((unsigned char)txStr[i++]);
}
unsigned char wifly_waitForText(char *text)
{
unsigned char retry = 255;
unsigned char matched = 0;
while ((retry-->0)&&(commComplete==0))
__delay_cycles(160000);
if (commComplete==0) return 0;
while ((text[matched]==wifly_rx[matched])&&(matched<255))
{
matched++;
if (text[matched]=='\0') return 1;
}
return 0;
}
unsigned int wifly_enterCommandMode()
{
unsigned char retry=20;
while (retry-->0)
{
UART_TX("\r\n\0");
__delay_cycles(250 * 16000);
UART_TX("\r\n\0"); // we send 2 times cr lf
// since the first one is only used to clear the wifly command buffer
if (wifly_waitForText("<2.32>\0")==1) return 1;
UART_TX("$$$\0");
__delay_cycles(250 * 16000);
// should receive "CMD"
if (wifly_waitForText("CMD\0")==1) return 1;
}
return 0;
}
The enterCommandMode procedure checks first if we are already in command mode.
In that case the wifly will respond to an empty command with a prompt with the version number, in my case this would be "<2.32>".
Once we are in command mode we can connect to a ssid
void wifly_connect(char *ssid,char *pwd)
{
UART_TX("set wlan auth 3\r\n\0"); // WPA mixed, might be different for you,
// check the RN XV user manual
__delay_cycles(160000);
UART_TX("set wlan ssid \0");
UART_TX(ssid);
UART_TX("\r\n\0");
__delay_cycles(160000);
UART_TX("set wlan phrase \0"); // you may need key instead,
// depending on your configuration
UART_TX(pwd);
UART_TX("\r\n\0");
__delay_cycles(160000);
UART_TX("join\r\n\0");
__delay_cycles(48000000); // wait 3 seconds, might actually take longer
}
void main(void)
{ // stop the watchdog
WDTCTL = WDTPW + WDTHOLD; // allow debugging
configClock();
configUART();
while (1)
{
if (wifly_enterCommandMode()==1)
{
wifly_connect("myssid\0","mypwd\0");
// do stuff here
// make sure you do not keep trying to connect if
// it is already connecting
}
}
}
Ok, this implementation is quite basic, but was enough in my case to see the wifly pop up with a dhcp assigned ip in the admin page of my router.
I will fine tune and expand this implementation in the next days and hopefully interface it with a simple webservice page to send and receive some data.
The RN XV, from Roving Networks is a versatile little device.
It is basically a wifi card with a serial port, designed to be easily connected to microcontrollers.
I previously used on my Arduino and even on my BeagleBone, where I used java (RXTX) to drive it.
I have a youtube video about the BeagleBone / wifly, but it's mainly about the Bone and RXTX than the RN XV, so I will not embed it here.
Did you ever work with old modems?
If so you are probably familiar with the Hayes protocol and the AT commands you sent over the serial port.
No, the RN XV does not use Hayes, but the concept is similar : you send commands in ASCII format to the serial port and in that way instruct the module to connect to a ssid, perform a http get etc.
The good thing about this is that it's easy to test the protocol just using an hyperterminal kind of software.
In windows I like to use Realterm, it's open source.
To connect the wifly to a PC you will need an FTDI usb interface (get yourself a couple of those from ebay if you don't have them already, they are extremely handy).
To easily work with the RN XV (other compatible modules might be slightly different in this regard, so check carefully your specific case) you will also need (or "you will be better of with") a breakout board for it. (it is cheap, no worries).
The reason you may want the breakout board is that the pin pitch of the RN XV is designed to match the XBee standard, which would not work with the common headers you normally use.
Final consideration : the wifly modules work at 3.3V which makes them perfect to work with the MSP430G2, should you use an AVR or other MCUs, make sure the serial communication runs ar 3.3V, else you need a logic level converter.
Let's connect the RN XV with the Launchpad :
In my example I am powering the wifly module from the Launchpad, the 3,3V is taken from pin 1 on the lp.
Besides Vcc and GND for now we will just need the UART rx and tx signals.
You may wonder why the wifly has so many pins.
Like Dave would say : "I am glad you asked!".
The Roving Networks wifi interface contains an MCU which obviously has GPIO and other features (including an ADC which I never tried so far, but it promises 14 bit resolution !!!).
The functionality of the contained mcu are accessible through the various pins, we will probably need to use some of those later on.
As a general consideration, a text based protocol is normally handy to implement an interface, it makes it easier to debug and it's normally quite flexible.
Unfortunately it may become difficult to manage if the amount of RAM you have at your disposal is limited, like in the case of the MSP430G2.
We then need to design the handling routines accordingly, we will not be able to allocate a big buffer to store incoming data to be processed asynchronously.
In general a synchronous approach would probably reduce the amount of needed memory and it could eventually work with the wifly protocol, however I am going for a simple asynchronous implementation, using the uart interrupt on the MSP430G2, just to make sure we do not miss any incoming char.
By default, the wifly uart starts at 9600 baud, 8 N 1.
Let's start configuring the clock and uart on the launchpad (details here) :
#include <msp430g2553.h>
// configure the CPU clock (MCLK)
// to run from DCO @ 16MHz and SMCLK = DCO / 4
void configClock()
{
BCSCTL1 = CALBC1_16MHZ; // Set DCO
DCOCTL = CALDCO_16MHZ;
BCSCTL2= DIVS_2 + DIVM_0; // divider=4 for SMCLK and 1 for MCLK
}
void configUART()
{
// set the pin mode 3 for pins 1 & 2 of port 1 (Uart mode)
P1SEL |= BIT1 + BIT2; // low bit = 1 for pin 1 and 2
P1SEL2 |= BIT1 + BIT2; // high bit = 1 for pin 1 and 2
// configure the UART
UCA0CTL0 = 0; //UART mode, No parity, LSB first, 8 data, 1 stop
UCA0CTL1 = UCSSEL_2; //use SCLK
UCA0BR0 = 0x1A; //lower byte of UCBR0. 26dec
//(4MHz / 9600 baud) see table 15-5
UCA0BR1 = 0x0; //upper byte of UCBR0.set to 0
UCA0MCTL = UCBRF_1 + UCBRS_0 + UCOS16; //sets UCBRFx to 1,
// UCBRSx tto 0 , UCOS16=1
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI **
UC0IE |= UCA0RXIE; // Enable USCI_A1 RX interrupt
_EINT(); // global enable interrupts
}
Now we need to create a simple interrupt handling procedure for the uart rx, it will fill a receive buffer.
Normally I would allocate 4Kb of ram for a uart rx buffer, but there is no way we can do that on the G2, so we will need to limit it to 256 bytes, if we play it smart, it should be enough.
char UART_buffer[256];
unsigned char bufPtr = 0;
Together with the buffer I declare a buffer pointer, now, there are different ways to manage a buffer, I am going for a "circular management" approach which is quite common in these situations.
The receiving (interrupt) routine will store the incoming char in UART_buffer[bufPtr] and then increment bufPtr, when the end of the buffer is reached, since bufPtr is a byte (unsigned char) it will restart automatically from 0.
If we wanted a buffer size different from 256 we would have needed an if statement to check if the end of the buffer was reached and in that case reset the pointer.
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
char c = UCA0RXBUF;
if ((c!='\n')&&(c!='\r'))
UART_buffer[bufPtr++] = c;
else
if (c=='\r') wifly_process(bufPtr);
}
The command protocol of the wifly uses ASCII text responses terminated by CR LF (\r\n) so we will use that to acknowledge that a response has been received and needs to be processed.
While we process a text returned from the wifly, other chars could be incoming at the same time, therefore we need to pass the position of the end of the text to be processed in this iteration.
So, what's happening is that while we are filling the uart rx buffer, in parallel we have a procedure that at each CRLF received extracts a single response line.
The process procedure knows up to which char it has to process since this is passed by the interrupt routine, but if also needs to know from which char to START processing.
In the current implementation (it can be improved) I am copying a single returned line into a separate buffer that will be processed later on.
Also I added a flag to identify if there is a complete text line ready to be processed.
char wifly_rx[128];
unsigned char processPtr = 0;
unsigned char commComplete = 0;
void wifly_process(unsigned char i)
{
unsigned char cnt = 0;
while (processPtr!=i)
wifly_rx[cnt++] = UART_buffer[processPtr++];
wifly_rx[cnt] = '\0';
commComplete=1;
}
I am adding a char 0 at the end of the buffer as it is needed by the string handling routines I created.
The first (a bit painful) thing you have to know when working with the wifly protocol is that it has two functioning modes :
The data mode and the command mode.
To send commands you need to enter in the command mode (fair, no?) which, via the UART is achieved by sending three dollar isngs ( $$$ ) not followed by a crlf and wait for 250 ms.
That's fairly easy and the module will answer with "CMD".
Practically it's less obvious than you may think.
Firts, you may already be in command mode and in that case you will not get any answer until you send a crlf, second in some cases the module may not respond (it improved with the latest firmware releases).
A typical case is while establishing a connection to a ssid.
For this reason in the latest firmware releases an alternative method to enter in command mode, was implemented and it is based on pulses sent through the GPIO.
We will not implement that one right now.
void UART_SendChar(unsigned char txChar)
{
while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF=txChar;
}
void UART_TX(char *txStr)
{
unsigned int i=0;
while(txStr[i]!=0)
UART_SendChar((unsigned char)txStr[i++]);
}
unsigned char wifly_waitForText(char *text)
{
unsigned char retry = 255;
unsigned char matched = 0;
while ((retry-->0)&&(commComplete==0))
__delay_cycles(160000);
if (commComplete==0) return 0;
while ((text[matched]==wifly_rx[matched])&&(matched<255))
{
matched++;
if (text[matched]=='\0') return 1;
}
return 0;
}
unsigned int wifly_enterCommandMode()
{
unsigned char retry=20;
while (retry-->0)
{
UART_TX("\r\n\0");
__delay_cycles(250 * 16000);
UART_TX("\r\n\0"); // we send 2 times cr lf
// since the first one is only used to clear the wifly command buffer
if (wifly_waitForText("<2.32>\0")==1) return 1;
UART_TX("$$$\0");
__delay_cycles(250 * 16000);
// should receive "CMD"
if (wifly_waitForText("CMD\0")==1) return 1;
}
return 0;
}
The enterCommandMode procedure checks first if we are already in command mode.
In that case the wifly will respond to an empty command with a prompt with the version number, in my case this would be "<2.32>".
Once we are in command mode we can connect to a ssid
void wifly_connect(char *ssid,char *pwd)
{
UART_TX("set wlan auth 3\r\n\0"); // WPA mixed, might be different for you,
// check the RN XV user manual
__delay_cycles(160000);
UART_TX("set wlan ssid \0");
UART_TX(ssid);
UART_TX("\r\n\0");
__delay_cycles(160000);
UART_TX("set wlan phrase \0"); // you may need key instead,
// depending on your configuration
UART_TX(pwd);
UART_TX("\r\n\0");
__delay_cycles(160000);
UART_TX("join\r\n\0");
__delay_cycles(48000000); // wait 3 seconds, might actually take longer
}
void main(void)
{ // stop the watchdog
WDTCTL = WDTPW + WDTHOLD; // allow debugging
configClock();
configUART();
while (1)
{
if (wifly_enterCommandMode()==1)
{
wifly_connect("myssid\0","mypwd\0");
// do stuff here
// make sure you do not keep trying to connect if
// it is already connecting
}
}
}
Ok, this implementation is quite basic, but was enough in my case to see the wifly pop up with a dhcp assigned ip in the admin page of my router.
I will fine tune and expand this implementation in the next days and hopefully interface it with a simple webservice page to send and receive some data.
Wednesday, September 12, 2012
One of these days...
Today the USA Ambassador to Libya was killed, together with some embassy personnel.
I want to put this straight : I am not American, I have no reason to prefer USA to other countries.
I do think it's a great country, like many others in the world, including Libya.
I am not christian, nor muslim, in fact most of the people would define me as atheist.
But I dream of a different world, we probably all do or at least this is what I sincerely hope.
The world I dream of does not need religions, not that I would forbid them should I have the power to do it, it really bothers me that you guys need them.
In my dream a good man or woman does not need to be a prophet, she/he can be smart, wise and contribute greatly to our history without the need of walking on the water or turning dead people into living beings.
Why can't we just have plain good people without making them prophets, saints (or heroes for what matters)?
And most of all, if you have to love your prophets, saints and heroes, do they really need to be so weak that they need your unconditioned support to protect them?
Can't they just deal themselves with whatever THEY may believe is an offense towards them?
Do you think they would not be at least as efficient as you are? So you think you are better than them?
There are no good religions, nor bad religions.
There are humans that rely on their rational brain to decide what to think, what to say and do.
Others instead prefer to give up their own thoughts and feed themselves with pre-digested ones that others prepared for them.
If you believe "holy books" do exist, then you definitely fall into this second group.
I cannot judge you, nor I am willing to, whatever way you want to go regarding this : you can be rational and decide to be responsible for your own actions or you can be "foolish" (as opposed to "rational", not meant as an offensive word) and let others tell you what to do.
Make your call, we probably dream of different worlds, but in the process, stop killing people in the name of the choice you made.
Just a piece of advice : if you are dreaming someone's else dream, it might be a good time to wake up.
I want to put this straight : I am not American, I have no reason to prefer USA to other countries.
I do think it's a great country, like many others in the world, including Libya.
I am not christian, nor muslim, in fact most of the people would define me as atheist.
But I dream of a different world, we probably all do or at least this is what I sincerely hope.
The world I dream of does not need religions, not that I would forbid them should I have the power to do it, it really bothers me that you guys need them.
In my dream a good man or woman does not need to be a prophet, she/he can be smart, wise and contribute greatly to our history without the need of walking on the water or turning dead people into living beings.
Why can't we just have plain good people without making them prophets, saints (or heroes for what matters)?
And most of all, if you have to love your prophets, saints and heroes, do they really need to be so weak that they need your unconditioned support to protect them?
Can't they just deal themselves with whatever THEY may believe is an offense towards them?
Do you think they would not be at least as efficient as you are? So you think you are better than them?
There are no good religions, nor bad religions.
There are humans that rely on their rational brain to decide what to think, what to say and do.
Others instead prefer to give up their own thoughts and feed themselves with pre-digested ones that others prepared for them.
If you believe "holy books" do exist, then you definitely fall into this second group.
I cannot judge you, nor I am willing to, whatever way you want to go regarding this : you can be rational and decide to be responsible for your own actions or you can be "foolish" (as opposed to "rational", not meant as an offensive word) and let others tell you what to do.
Make your call, we probably dream of different worlds, but in the process, stop killing people in the name of the choice you made.
Just a piece of advice : if you are dreaming someone's else dream, it might be a good time to wake up.
Monday, September 10, 2012
Driving a Mosfet with PWM
I played a bit with mosfets and finally managed to set up my first test circuit to drive them with the MSP430G2.
While in theory it's all quite simple, the correct selection of components to be used is extremely important.
The basic Idea is that the MCU generates a pwm signal which controls the gate of the mosfet.
Practically a few things must be considered, in fact you might get away with it easily if you do not need a lot of current to go through your power mosfet.
If you have no idea on how mosfets work, you can check my post here.
It all comes down to the internal resistance between Drain and Source, you need it very high when the device is OFF and very low when the device is ON.
That's because if you are planning to have several Amps going through your transistor when it is on, you want a very low internal resistance or you will dissipate a considerable amount of heat (which is power you are wasting in whatever you are doing -except if you are doing a heating system-).
P = RI^2 from Ohm's law, so say you have 20 Amps and your R is 1 Ohm, you are dissipating 1*20*20 = 400W of power.
Mosfets tend to have a gate threshold (Vgs) at around 2 to 4V, however, while they "open" at that low voltage, their internal Rds resistance is still pretty high.
Every device has its own Rds curve in relation to the Vgs, but normally you want to drive the gate at about 12V or more.
You can find on the market some "logic level" mosfets that can be driven directly with a TTL signal, however they are normally not suitable to drive high currents and high voltages.
I chose a N channel mosfet for my experiment, particularly the IRF3710.
This device can deliver 46Amps at 100V with a reasonably low RdsON value (about 28mOhm) with Vgs over 7V.
Definitely it is not possible to drive it with a 3.3V signal.
A bit of math let's us find P = 46*46*0.028 = 60W which is still a lot, but I will probably be working in the range of 10Amps with way better results.
The problem with these devices is that to be able to let such big currents to pass through the channel, they need to create quite a big channel.
To open the N channel in the P doped semiconductor substrate, we will need a lot of charges, meaning the gate will act as a reasonably big capacitor.
We definitely need to charge that capacitor as quick as possible as a partial charge would result in a lower gate voltage which in turn would generate a higher Rds.
This means that not only we need to provide a sufficiently high voltage on the gate, but also we need to provide enough amount of current.
That's where gate drivers come in help.
They basically act as a "primary stage" mosfet to raise voltage and current to drive more efficiently the power device gate.
I was suggested to look into the Microchip TC4420 and similar devices.
This one particularly contains two logic level mosfets configured as a totem pole, that can output 18V and up to 6A.
These little buddies make your life way easier.
I first tested their output signal by feeding them the pwm signal of the MSP430G2 on one side and a 12V supply on the other.
(if you want to know how to output a pwm signal from the msp430g2, you can check here )
Despite the fact that I arranged the test on a solderless breadboard, I managed to obtain some decent frequencies.
As you can see in the picture I definitely have some (non desired) ringing, but that's probably reasonable if you consider all those jumper wires going around in the breadboard.
Normally with these circuits you need to keep very short traces on a nicely designed PCB, that would definitely help in reducing parasitic effects (inductance/capacitance etc).
Plus I did not add any filtering cap for now, which would also help.
The waveform in the picture is at 1.32MHz, not too bad after all on a breadboard.
The next step was to add the power mosfet, so I did setup a test circuit like this one :
The two channels of the Oscilloscope are used to plot the output of the gate driver and the output of the power mosfet.
A Load resistor is added to simulate some load on the line... and at my first attempt I was able to get the "magic smoke" out :)
The load was too high, not a problem for the mosfet because it can handle 46Amp and the PSU can only provide 20, it was not a problem for the PSU either... but the tiny jumper wire did not appreciate much the glorious 20A pulses.
Now they smell funny and they are bit "crusty", but they still work (with a higher R Load impedance).
Channel 1 of the scope measures Vds (voltage between Drain and Source) which goes to (almost) zero when the gate is fully open.
Technically it's the voltage across the internal Rds resistor, so if it goes nicely down to zero it means we successfully drive the gate.
I will need to repeat this test with a higher load on the line (but not on the breadboard, melted plastic does not smell really nice).
Channel 1 is red and the volt scale is 2V per division.
You can see the zero level being marked by the little (1) red marker on the left side.
Channel 2 is yellow, showing the gate driver output, the two signals are inverted since when the gate signal (yellow) is high, it closes the circuit, so the Vds (red) drops to zero.
That's what I get at 80Khz.
I increased the frequency at about 320KHz and the result is visible in the picture below.
Both channels are now at 2V per division, aligned to their zero V.
You can see the rising edge of the Vds (red) being a bit "slow", that's definitely something that needs to be improved, which I assume can be achieved by discharging quicker the mosfet's gate.
Indeed proper cabling/pcb design is also needed, in fact the TC4420 can output up to 6A, no way that's going to happen using those tiny jumper wires.
I don't think it's something I can work on on a solderless breadboard like that, I probably need a better layout and definitely shorter connections.
Next step will be to add some caps, an inductive load on the output and a freewheeling diode, that's where the real "magic smoke" could happen :)
Update : adding a 10Ohm gate resistor on the mosfet the signal becomes like this :
Normally a fast diode should be placed in parallel with the resistor, to improve the shutdown of the gate (or at least this is what I understood reading this interesting document)
While in theory it's all quite simple, the correct selection of components to be used is extremely important.
The basic Idea is that the MCU generates a pwm signal which controls the gate of the mosfet.
Practically a few things must be considered, in fact you might get away with it easily if you do not need a lot of current to go through your power mosfet.
If you have no idea on how mosfets work, you can check my post here.
It all comes down to the internal resistance between Drain and Source, you need it very high when the device is OFF and very low when the device is ON.
That's because if you are planning to have several Amps going through your transistor when it is on, you want a very low internal resistance or you will dissipate a considerable amount of heat (which is power you are wasting in whatever you are doing -except if you are doing a heating system-).
P = RI^2 from Ohm's law, so say you have 20 Amps and your R is 1 Ohm, you are dissipating 1*20*20 = 400W of power.
Mosfets tend to have a gate threshold (Vgs) at around 2 to 4V, however, while they "open" at that low voltage, their internal Rds resistance is still pretty high.
Every device has its own Rds curve in relation to the Vgs, but normally you want to drive the gate at about 12V or more.
You can find on the market some "logic level" mosfets that can be driven directly with a TTL signal, however they are normally not suitable to drive high currents and high voltages.
I chose a N channel mosfet for my experiment, particularly the IRF3710.
This device can deliver 46Amps at 100V with a reasonably low RdsON value (about 28mOhm) with Vgs over 7V.
Definitely it is not possible to drive it with a 3.3V signal.
A bit of math let's us find P = 46*46*0.028 = 60W which is still a lot, but I will probably be working in the range of 10Amps with way better results.
The problem with these devices is that to be able to let such big currents to pass through the channel, they need to create quite a big channel.
To open the N channel in the P doped semiconductor substrate, we will need a lot of charges, meaning the gate will act as a reasonably big capacitor.
We definitely need to charge that capacitor as quick as possible as a partial charge would result in a lower gate voltage which in turn would generate a higher Rds.
This means that not only we need to provide a sufficiently high voltage on the gate, but also we need to provide enough amount of current.
That's where gate drivers come in help.
They basically act as a "primary stage" mosfet to raise voltage and current to drive more efficiently the power device gate.
I was suggested to look into the Microchip TC4420 and similar devices.
This one particularly contains two logic level mosfets configured as a totem pole, that can output 18V and up to 6A.
These little buddies make your life way easier.
I first tested their output signal by feeding them the pwm signal of the MSP430G2 on one side and a 12V supply on the other.
(if you want to know how to output a pwm signal from the msp430g2, you can check here )
Despite the fact that I arranged the test on a solderless breadboard, I managed to obtain some decent frequencies.
As you can see in the picture I definitely have some (non desired) ringing, but that's probably reasonable if you consider all those jumper wires going around in the breadboard.
Normally with these circuits you need to keep very short traces on a nicely designed PCB, that would definitely help in reducing parasitic effects (inductance/capacitance etc).
Plus I did not add any filtering cap for now, which would also help.
The waveform in the picture is at 1.32MHz, not too bad after all on a breadboard.
The next step was to add the power mosfet, so I did setup a test circuit like this one :
The two channels of the Oscilloscope are used to plot the output of the gate driver and the output of the power mosfet.
A Load resistor is added to simulate some load on the line... and at my first attempt I was able to get the "magic smoke" out :)
The load was too high, not a problem for the mosfet because it can handle 46Amp and the PSU can only provide 20, it was not a problem for the PSU either... but the tiny jumper wire did not appreciate much the glorious 20A pulses.
Now they smell funny and they are bit "crusty", but they still work (with a higher R Load impedance).
Channel 1 of the scope measures Vds (voltage between Drain and Source) which goes to (almost) zero when the gate is fully open.
Technically it's the voltage across the internal Rds resistor, so if it goes nicely down to zero it means we successfully drive the gate.
I will need to repeat this test with a higher load on the line (but not on the breadboard, melted plastic does not smell really nice).
Channel 1 is red and the volt scale is 2V per division.
You can see the zero level being marked by the little (1) red marker on the left side.
Channel 2 is yellow, showing the gate driver output, the two signals are inverted since when the gate signal (yellow) is high, it closes the circuit, so the Vds (red) drops to zero.
That's what I get at 80Khz.
I increased the frequency at about 320KHz and the result is visible in the picture below.
Both channels are now at 2V per division, aligned to their zero V.
You can see the rising edge of the Vds (red) being a bit "slow", that's definitely something that needs to be improved, which I assume can be achieved by discharging quicker the mosfet's gate.
Indeed proper cabling/pcb design is also needed, in fact the TC4420 can output up to 6A, no way that's going to happen using those tiny jumper wires.
I don't think it's something I can work on on a solderless breadboard like that, I probably need a better layout and definitely shorter connections.
Next step will be to add some caps, an inductive load on the output and a freewheeling diode, that's where the real "magic smoke" could happen :)
Update : adding a 10Ohm gate resistor on the mosfet the signal becomes like this :
Normally a fast diode should be placed in parallel with the resistor, to improve the shutdown of the gate (or at least this is what I understood reading this interesting document)
Subscribe to:
Posts (Atom)