Hi. I build a arduino pro mini based PPM receiver and transmitter to control my quadcopter. They are copy's of iforce2d cheap-ass projects - Cheap-ass quadcopter build Part 12 - Arduino conversion of HK transmitter - YouTube
I added a LED to show me when RX and TX are connected and I got it working but I would like to put it blinking when not connected and solid when they are but the blinking part is over my head, because I need to use millis and not delay. So any help would be appreciated
Thanks.
I fitted it to old Hitec 35mhz FM receiver case:
/*
A basic receiver using the nRF24L01 module to receive 10 channels and convert them to PPM.
*/
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
////////////////////// PPM CONFIGURATION//////////////////////////
#define channel_number 10 //set the number of channels
#define sigPin 2 //set PPM signal output pin on the arduino
#define PPM_FrLen 27000 //set the PPM frame length in microseconds (1ms = 1000µs)
#define PPM_PulseLen 400 //set the pulse length
//////////////////////////////////////////////////////////////////
const int ledPin = 3; // Led pin 3
int ppm[channel_number];
const uint64_t pipeIn = 0xE8E8F0F0E1LL;
RF24 radio(9, 10);
// The sizeof this struct should not exceed 32 bytes
struct MyData {
byte throttle;
byte yaw;
byte pitch;
byte roll;
byte dial1;
byte dial2;
byte switches; // bitflag
};
MyData data;
void resetData()
{
// 'safe' values to use when no radio input is detected
data.throttle = 0;
data.yaw = 127;
data.pitch = 127;
data.roll = 127;
data.dial1 = 0;
data.dial2 = 0;
data.switches = 0;
setPPMValuesFromData();
}
void setPPMValuesFromData()
{
ppm[0] = map(data.throttle, 0, 255, 1000, 2000);
ppm[1] = map(data.yaw, 0, 255, 1000, 2000);
ppm[2] = map(data.pitch, 0, 255, 1000, 2000);
ppm[3] = map(data.roll, 0, 255, 1000, 2000);
ppm[4] = map(data.dial1, 0, 255, 1000, 2000);
ppm[5] = map(data.dial2, 0, 255, 1000, 2000);
ppm[6] = data.switches & 0x1 ? 2000 : 1000;
ppm[7] = data.switches & 0x2 ? 2000 : 1000;
ppm[8] = data.switches & 0x4 ? 2000 : 1000;
ppm[9] = data.switches & 0x8 ? 2000 : 1000;
}
/**************************************************/
void setupPPM() {
pinMode(sigPin, OUTPUT);
digitalWrite(sigPin, 0); //set the PPM signal pin to the default state (off)
cli();
TCCR1A = 0; // set entire TCCR1 register to 0
TCCR1B = 0;
OCR1A = 100; // compare match register (not very important, sets the timeout for the first interrupt)
TCCR1B |= (1 << WGM12); // turn on CTC mode
TCCR1B |= (1 << CS11); // 8 prescaler: 0,5 microseconds at 16mhz
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
sei();
}
void setup()
{
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);
resetData();
setupPPM();
// Set up radio module
radio.begin();
radio.setDataRate(RF24_250KBPS); // Both endpoints must have this set the same
radio.setAutoAck(false);
radio.openReadingPipe(1,pipeIn);
radio.startListening();
}
/**************************************************/
unsigned long lastRecvTime = 0;
void recvData()
{
while ( radio.available() ) {
radio.read(&data, sizeof(MyData));
lastRecvTime = millis();
digitalWrite(ledPin, HIGH); // Turn status LED on
}
}
/**************************************************/
void loop()
{
recvData();
unsigned long now = millis();
if ( now - lastRecvTime > 1000 ) {
// signal lost?
resetData();
digitalWrite(ledPin, LOW); // Turn status LED off
}
setPPMValuesFromData();
}
/**************************************************/
//#error This line is here to intentionally cause a compile error. Please make sure you set clockMultiplier below as appropriate, then delete this line.
#define clockMultiplier 2 // set this to 2 if you are using a 16MHz arduino, leave as 1 for an 8MHz arduino
ISR(TIMER1_COMPA_vect){
static boolean state = true;
TCNT1 = 0;
if ( state ) {
//end pulse
PORTD = PORTD & ~B00000100; // turn pin 2 off. Could also use: digitalWrite(sigPin,0)
OCR1A = PPM_PulseLen * clockMultiplier;
state = false;
}
else {
//start pulse
static byte cur_chan_numb;
static unsigned int calc_rest;
PORTD = PORTD | B00000100; // turn pin 2 on. Could also use: digitalWrite(sigPin,1)
state = true;
if(cur_chan_numb >= channel_number) {
cur_chan_numb = 0;
calc_rest += PPM_PulseLen;
OCR1A = (PPM_FrLen - calc_rest) * clockMultiplier;
calc_rest = 0;
}
else {
OCR1A = (ppm[cur_chan_numb] - PPM_PulseLen) * clockMultiplier;
calc_rest += ppm[cur_chan_numb];
cur_chan_numb++;
}
}
}