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)