Thursday, April 16, 2009

TinyOS: Control servo motor using telosb







For the class project, we made a robot that can be controlled by a Telosb mote. We used two Parallax modified (we did not modify it. The one can continuously rotate is called modified servo) servo motor. The servo motor is shown in figure. This servo motor can be controlled by PWM. The servo motor PWM timing diagram is shown in Figure. The wiring diagram for Parallax servo motor is shown in Figure. So the servo motor can be controlled by providing PWM to the I/O pin. You can try this by using a simple ciruit. PWM can also control the speed of the servo motor.

Now, lets see how we connect the servo motor to the Telosb. Telosb has two expansion connectors. We use the 10-pin connector. Pin 9 is ground. We used two servo motors, so that the robot can turn in Tank style. Therefore, we used Pin-3 and Pin-5 to control two servo motors. To forward straight, two servo motor must rotate in opposite direction. You will see it when you construct your robot. Now, we Telosb ADC converer to send PWM signal to Pin-3 and Pin-5. From the msp430 manual, you know that pins 60 and 61 are the ones you want to use. There is the NesC code for that.

In your configuration file:

components HplMsp430GeneralIOC;

App.Pin0 ->HplMsp430GeneralIOC.Port60;
App.Pin1 ->HplMsp430GeneralIOC.Port61;

In Module use the interfaces:

interface HplMsp430GeneralIO as Pin0;
interface HplMsp430GeneralIO as Pin1;

That is it. Now only thing you have to is is call
call Pin0.clr() or call Pin1.set();
in your timer. You can try this on your Oscilloscope if you are not sure. The only thing left is timing. We used three timers. One with period 18. Other two timers are fires once in 1 or 2 ms after the first timer starts. Here is the code for that. This code randomly sets the movement of the robot.

event void Boot.booted()
{
call Timer0.startPeriodic(18);
}


void forward()
{
call Timer1.startOneShot(1);
call Timer2.startOneShot(2);
}

void reverse()
{
call Timer1.startOneShot(2);
call Timer2.startOneShot(1);

}

void turnright()
{
call Timer1.startOneShot(2);
call Timer2.startOneShot(2);
}
void turnleft()
{
call Timer1.startOneShot(1);
call Timer2.startOneShot(1);
}

event void Timer0.fired()
{
count++;
call Pin1.set();
call Pin0.set();

switch(action){
case 1:
forward(); break;
case 2:
reverse(); break;
case 3:
turnright();break;
case 4:
turnleft();break;
default:
forward();

}

if(count % 100 == 0)
{

action = call Random.rand16() % 4 + 1;
if(action == 1 || action == 2)
count = 0;
else
count = 80;
}
}


event void Timer1.fired()
{
call Pin1.clr();

}
event void Timer2.fired()
{
call Pin0.clr();
}

That is pretty much everything. The source code is here: servo-telosb.zip

Tuesday, April 14, 2009

TinyOS: setting transmission power for telosb (cc2420 chips)

A homework asked us to localize a mobile mote using RSSI. In short range, the RSSI is inaccurate. To reduce the interference between motes, I reduced the transmission power of mobile mote. It worked very well. Only close neighbors received the signal from the mobile mote. Here is the mobile mote code.
------------------------------------
File: LowPowerSendAppC.nc

/*
* Setting Transmission Power for CC2420 Chips (Telosb, Micaz)
*
* Author: Anwar Mamat anwar at cse.unl.edu
* 04/01/2009
*/


enum {
AM_RSSIMSG = 10
};

typedef nx_struct RssiMsg{
nx_int16_t rssi;
} RssiMsg;

configuration LowPowerSendAppC{

}
implementation {
components ActiveMessageC, MainC;
components new AMSenderC(AM_RSSIMSG) as RssiMsgSender;
components new TimerMilliC() as SendTimer;
components CC2420ActiveMessageC;

components LowPowerSendC as App;


App.Boot -> MainC;
App.SendTimer -> SendTimer;

App.RssiMsgSend -> RssiMsgSender;
App.RadioControl -> ActiveMessageC;
App-> CC2420ActiveMessageC.CC2420Packet;
}

-------------------------------------
File: LowPowerSendC.nc

module LowPowerSendC{
uses interface Boot;
uses interface Timer as SendTimer;
uses interface AMSend as RssiMsgSend;
uses interface SplitControl as RadioControl;
uses interface CC2420Packet;

}
implementation{

message_t msg;
uint16_t SEND_INTERVAL_MS = 100;
uint8_t TRANS_POWER = 3;

event void Boot.booted(){
call RadioControl.start();
}

event void RadioControl.startDone(error_t result){
call SendTimer.startPeriodic(SEND_INTERVAL_MS);
}

event void RadioControl.stopDone(error_t result){}


event void SendTimer.fired(){
call CC2420Packet.setPower(&msg, TRANS_POWER);
call RssiMsgSend.send(AM_BROADCAST_ADDR, &msg, sizeof(RssiMsg));
}

event void RssiMsgSend.sendDone(message_t *m, error_t error){}
}

--------------------------------
File: Makefile

COMPONENT=LowPowerSendAppC
include $(MAKERULES)

Monday, March 30, 2009

HelloWorld for TinyOS

This semester I took "Embedded Systems". I have always liked playing with the sensors and ADC kind of stuff. I checked out few Telosb motes from the lab, installed TinyOS 2.1 on my OpenSuse11.1 desktop, and tried my first "HelloWorld" program. The "HelloWorld" for TinyOS is not that straightforward. Here are the step to make the "HelloWorld" code work on your mote.

1. Install TinyOS. Please refer http://www.tinyos.net/tinyos-2.x/doc/html/install-tinyos.html
2. Make sure you have the correct version of Java on your machine. The default Java on your machine may confilct with the required one.
3. mkdir HelloWorld
4. HelloWorldAppC.nc file:
configuration HelloWorldAppC {
}
implementation {
components HelloWorldC;
components MainC,LedsC;
components new TimerMilliC() as Timer0;

HelloWorldC.Boot-> MainC.Boot;
HelloWorldC.Leds-> LedsC;
HelloWorldC.Timer0->Timer0;
}
5. HelloWorldC.nc file:
module HelloWorldC{
uses{
interface Boot;
interface Leds;
interface Timer as Timer0;
}
}

implementation{
uint16_t count = 0;
event void Boot.booted()
{
call Timer0.startPeriodic(500);
}

event void Timer0.fired()
{
count++;
if (count & 0x0004)
call Leds.led2On();
else
call Leds.led2Off();
if (count & 0x0002)
call Leds.led1On();
else
call Leds.led1Off();
if (count & 0x0001)
call Leds.led0On();
else
call Leds.led0Off();
}
}
6. The Makefile:
COMPONENT=HelloWorldAppC
include $(MAKERULES)

7. So, now you have the HelloWorldAppC.nc, HelloWorldC.nc and Makefile, 3 files in your folder.
8. compile the code: make telosb or make micaz
9. If no error messages, then upload the binary to the mote:
make telosb reinstall
10. Now, you should see the mote saying "HelloWorld" by blinking the 3 Leds.

That is it. Enjoy your TinyOS.

Thursday, February 19, 2009

enumerate all cycles in a graph c++ code

Finding all cycles in an undirected graph is an interesting problem. Few days ago, I tried to count all the cycles in a K6, a complete graph with 6 vertices. Finding the 7 cycles from a K4 is easy. But finding the 197 cycles in a K6 is not that trivial. Then I wrote a c++ code to enumerate all cycles in a graph. I tested it on some connected graphs and the results seem correct. Here are the results for the complete graphs, which I can verify by (sum_{k=3}^{n}{1/2 * nCr(n,k)*(k-1)!}.
Number of vertices, number of cycles
3, 1
4,7
5,37
6,197
7,1172
8,8018
9,62814
10,556014
11,5,488,059
20,174548332364311563

Here is the code: graph.txt allcycles.cpp

Wednesday, February 18, 2009

C++ STL SET example: How to insert objects (ADT) into the set

If your set elements are ADTs or class objects, the elements must be comparable to be inserted into SET container. There is an example. Set example

Tuesday, February 10, 2009

ACM Programming Contest Problem: Alpha code
Alice and Bob need to send secret messages to each other and are discussing ways to encode their messages:
Alice: “Let’s just use a very simple code: We’ll assign ‘A’ the code word 1, ‘B’ will be 2,
and so on down to ‘Z’ being assigned 26.”
Bob: “That’s a stupid code, Alice. Suppose I send you the word ‘BEAN’ encoded as 25114.
You could decode that in many different ways!”
Alice: “Sure you could, but what words would you get? Other than ‘BEAN’, you’d get
‘BEAAD’, ‘YAAD’, ‘YAN’, ‘YKD’ and ‘BEKD’. I think you would be able to figure out the
correct decoding. And why would you send me the word ‘BEAN’ anyway?”
Bob: “OK, maybe that’s a bad example, but I bet you that if you got a string of length 500
there would be tons of different decodings and with that many you would find at least two
different ones that would make sense.”
Alice: “How many different decodings?”
Bob: “Jillions!”

For some reason, Alice is still unconvinced by Bob’s argument, so she requires a program that will
determine how many decodings there can be for a given string using her code.
Input
Input will consist of multiple input sets. Each set will consist of a single line of digits representing a
valid encryption (for example, no line will begin with a 0). There will be no spaces between the digits.
An input line of ‘0’ will terminate the input and should not be processed
Output
For each input set, output the number of possible decodings for the input string. All answers will be
within the range of a long variable.
Sample Input
25114
1111111111
3333333333
0
Sample Output
6
89
1

Solution:

When a new digit A is added to the existing digits BCDE, there are 3 cases:
1. If AB can't combine (AB > 26), the number of decodings is same.
2. If AB can combine, but BC can't combine, the number of decodings double.
3. If AB and BC both can combine, then the number of decodings is equal to the sum of previous two decodings.

You notice that, if all the numbers can combine with neighbours, then the number of decodings is Fibonacci number.

Here is the C++ code.


//============================================================================
// Name : ACM_Alpha_Code.cpp
// Author : Anwar Mamat
//============================================================================

#include
#include
using namespace std;

int main() {

ifstream fin("data.txt");
string strCode;
int i = 0;
int codeLength = 0;
int firstDigit = 0;
int secondDigit = 0;
int sum[100]={1};
int currentDigit = 0;

while(fin >> strCode){ //read number of data set
if(strCode == "0") break;
cout << "Code:" << codelength =" strCode.length();" i =" 1;" currentdigit =" strCode.at(codeLength"> 26 ){//if the new digit can't combine with the first digit
sum[i] = sum[i-1]; //the number of decodings are same
}
else if(firstDigit * 10 + secondDigit > 26) //if first digit can't combine with second digit
sum[i] = sum[i-1] * 2; //number of decodings doubles
else{
if(i == 1)
sum[i] = 1;
else
sum[i] = sum[i-1] + sum [i - 2]; //if new digit, fist digit and second digits can combine,
} //number of decodings is Fibonacci number.
secondDigit = firstDigit;
firstDigit = currentDigit;
}
//for(i = codeLength ; i > 0 ; i--)
// cout <<"Sum[" << i << "]=" << sum[i] << endl;

cout <<"Sum=" << sum[codeLength] << endl;
}
fin.close();
return 0;
}



The data.txt file:
25114
1111111111
33333333333333333
0