ADVERTISEMENT
|
Controlling an RC car with AD9850 dds module and an arduino |
If you have an rc car, an
ad9850 board (cheap modules available on ebay) and an arduino uno, it is possible to convert them to a computer controlled or programmable rc car. After seeing a post on converting a cheap rc car by
jon, to a programmable one by modifying the remote control with an arduino, i decided to make a universal controller which doesn't need to solder or modify the cars electronics. So this approach can add an independent control channel and some fun with decryping and cloning rc remotes of simple toy grade cars (without any encryption)
RC car control signals
A simple rc car uses an amplitude modulated carrier (rf signal) to send the control signal. So most of simple toys uses a 4 pulses of a specific length followed by a multiple of pulses to send a specific command (more of this in a later post). I used gnuradio and funcube dongle to capture the signals and to analyse the control signals. Brandon has a
similar project where he used a raspberry pi's pll to directly generate the rf signals and brute force to identify the correct pulse lengths. You can use audacity to measure the pulse lengths after capturing the audio from a radio receiver or sdr tuned to 27mhz signals from the rc remote [read more on
decoding the signals using sdr].
AD9850 control signals and speed issues
One of the challenge with this project was the time delays while updating the ad9850 frequency words via arduino. It was overcomed by using the hardware spi for controlling the frequency and usng the PORT commands instead of the digitalwrites. An other small issue was with analogue read delays, which was used to read the keypad inputs. This was solved with an adc update and later i found that all these issues were addressed in a project by
Zisis Chiotis which implements an fm modulation on an arduino! (at around 16khz)
|
connecting ad9850 to arduino spi pins |
|
Using a single analogue pin to assign multiple key functions to control the rc car |
Data connections to AD9850. See
here for the corresponding pins
- MOSI = DATA (pin 11 on uno)
- CLK = W_CLK (pin 13 on uno)
- FU_UD (PIN 6 on uno) (see port command here)
- GND = RESET
Source code
//#AD9850 rc remote control
//blog.riyas.org
//courtesy to Zisis Chiotis
#define PLEN 550 //optimised pulse length adjust this to match your remote:-audacity and sdr
#define PRELEN PLEN*3
#define FREQUENCY 542879
#define FREQUENCY2 0
#define btnRIGHT 0
#define btnUP 1
#define btnDOWN 2
#define btnLEFT 3
#define btnNONE 4
int adc_key_in = 0;
int key = 0;
#include <SPI.h>
uint32_t frequency = FREQUENCY; //The desired frequency must be divided by 50 ex. 34,7MHz/50 = 694000
uint32_t tword = frequency * 3436 / 100; //tuning word calculation
byte W[5] = { 0, 0, 0, 0, 0 };
const unsigned char PS_128 = (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); //these are the prescalers for the ADC sampling rate.
const unsigned char PS_32 = (1 << ADPS2) | (1 << ADPS0);
const unsigned char PS_16 = (1 << ADPS2);
int mic = 512;
void
setup ()
{
Serial.begin (9600);
DDRD = DDRD | B01100000; //
PORTD = 0x00;
// Serial.begin(115200); // everything can be controlled by serial comm
pinMode (A0, INPUT); // here comes the audio frequency in
SPI.setDataMode (SPI_MODE0); // mode 0 seems to be the right one
SPI.setClockDivider (SPI_CLOCK_DIV2); // this is pretty fast
SPI.setBitOrder (LSBFIRST); // AD9850 wants LSB first
SPI.begin ();
// set up the ADC
ADCSRA &= ~PS_128; // remove bits set by Arduino library
ADCSRA |= PS_32; // setting the sampling rate at 16MHz/32 this makes the analogRead() complete in around 40μs
}
void
loop ()
{
key = read_key ();
switch (key)
{
case btnRIGHT:
{
Serial.println ("FORWARD");
sendcommand (10);
break;
}
case btnLEFT:
{
Serial.println ("RIGHT");
sendcommand (34);
break;
}
case btnUP:
{
Serial.println ("BACKWARD");
sendcommand (40);
break;
}
case btnDOWN:
{
Serial.println ("LEFT");
sendcommand (28);
break;
}
case btnNONE:
{
//Serial.println("NONE");
break;
}
}
}
void
preample (int len)
{
int i;
for (i = 0; i < len; i++) {
setfreq (FREQUENCY);
delayMicroseconds (PRELEN);
setfreq (FREQUENCY2);
delayMicroseconds (PLEN);
}
}
void
command (int len)
{
int i;
for (i = 0; i < len; i++) {
setfreq (FREQUENCY);
delayMicroseconds (PLEN);
setfreq (FREQUENCY2);
delayMicroseconds (PLEN);
}
}
void
setfreq (uint32_t frequency)
{
tword = frequency * 1718; //calculating the tuning word for AD9850
W[0] = (byte) tword;
W[1] = (byte) (tword >> 8);
W[2] = (byte) (tword >> 16); //converting it to bytes
W[3] = (byte) (tword >> 24);
W[4] = 0; //phase zero
//start sending with spi interface
PORTD = B01000000;
PORTD = 0x00; //pulse FU_UD
for (int j = 0; j < 5; j++) {
SPI.transfer (W[j]); //send the word
}
PORTD = B01000000;
PORTD = 0x00; //pulse FU_UD
}
int
read_key ()
{
adc_key_in = analogRead (0);
if (adc_key_in > 600)
return btnNONE;
if (adc_key_in > 500)
return btnRIGHT;
if (adc_key_in > 450)
return btnUP;
if (adc_key_in > 400)
return btnDOWN;
if (adc_key_in < 400)
return btnLEFT;
return btnNONE;
}
void
sendcommand (int n)
{
for (int i = 0; i < 5; i++) {
preample (4);
command (n);
}
}
end
What a wonderful project! Well done and thanks for the reference! Keep up with good ideas like this!
ReplyDeletehi,
ReplyDeleteThanks for sharing this project. I've try it with three 27MHZ cars but there is no effects. Is there some value to adjust please?
Thanks
Arnaud
Tweak PLEN (pulse length)
DeleteHow does the AD9850 send the signal? I don't see an antenna in the video, so where is the RF signal coming from?
ReplyDeleteA good antenna will improve the range. I just used a piece of wire hooked to the rf/ clock output of the dds chip
DeleteWhich pin is that? Also which pins need to be connected to the 5V power?
DeleteYou wrote pin 7 for FU_UD, but you are mapping to Arduino digital pins 5 & 6 in setup than later you are mapping only pin 6. I think if you correct the type you can save people some time because its not clear using port registers that its wrong.
ReplyDeleteThanks Michael. Corrected the typo and you are right as it takes a while to sort it out due to port manipulation.
DeleteI have an RC controlled Protocol Helicopter which will no longer turn on (same thing that has happened to my RC 27 MHz train which is what brought me here). I believe the pot which is also the on/off switch has broken inside and I have not been able to locate a replacement. If you are looking for another project please consider the Helicopter my Grandson would love to see fly for 4 minutes.
ReplyDeleteI know that you done this project long time ago was interested you think it can be realized with LTC6904 ?
ReplyDelete