Hmm I’m at work and I don’t have time to sneakily write you some code until I get home, but you can have this theory to start with
So to simplify the goal a bit, you want to do two distinct things: 1) read an RC receiver signal as a range, let’s say 0 - 1023, and 2) output a 1KHz PWM signal at a duty cycle of 0 - 100%, mapped from the earlier range.
Reading a receiver signal is pretty easy, but not as easy to do efficiently. You can easily use pulseIn() to read a receiver’s signal, but that has the disadvantage of making the code wait until the next signal starts every time, which means you won’t be able to generate the PWM output signal (because the code will be spending most of its time waiting). Instead you should use interrupts.
To generate a 1KHz PWM signal, we can’t use any automatic solutions without changing the timer frequencies of the Arduino, which messes with the millis()
and other timer functions. That wouldn’t be a problem except that we need the timer functions for writing the PWM signal to the LEDs.
Actually you know what. This doesn’t seem that hard. Here, try this code. Plug your receiver channel into pin A0 (and the ground of the receiver into a GND pin on the Arduino obviously - I’m hoping you know the hardware side of this well enough). Plug the LED controller’s PWM pin into pin 9 of the Arduino (idk why pin 9, I just picked one at random). Then just try out the code! It’s totally untested but I’m hoping it should just work. The PWM signal might be too rough; I’m just hoping the Arduino will be fast enough that a C-coded 1KHz PWM signal generator should work fine. This is one of these “suck it and see” situations.
Full disclosure, I didn’t write most of this code. I just grabbed the code off the page linked above on the interrupt method and modified it. I wrote the PWM bit myself though. Only the doPWM()
section and the associated variables are written in my style; everything else is gross and messy-looking
#include <EnableInterrupt.h>
#define SERIAL_PORT_SPEED 57600
#define RC_NUM_CHANNELS 1
#define RC_CH3 0
#define RC_CH3_INPUT 2
uint16_t rc_values[RC_NUM_CHANNELS];
uint32_t rc_start[RC_NUM_CHANNELS];
volatile uint16_t rc_shared[RC_NUM_CHANNELS];
int percentage = 0;
unsigned long lastPwmStart = 0;
const byte pwmPin = 0;
void rc_read_values() {
noInterrupts();
memcpy(rc_values, (const void *)rc_shared, sizeof(rc_shared));
interrupts();
}
void calc_input(uint8_t channel, uint8_t input_pin) {
if (digitalRead(input_pin) == HIGH) {
rc_start[channel] = micros();
} else {
uint16_t rc_compare = (uint16_t)(micros() - rc_start[channel]);
rc_shared[channel] = rc_compare;
}
}
void calc_ch3() { calc_input(RC_CH3, RC_CH3_INPUT); }
void setup() {
//Serial.begin(SERIAL_PORT_SPEED);
pinMode(RC_CH3_INPUT, INPUT);
pinMode(pwmPin, OUTPUT);
enableInterrupt(RC_CH3_INPUT, calc_ch3, CHANGE);
}
void loop() {
rc_read_values();
percentage = map(percentage, 1000, 2000, 0, 100); //assume the receiver is outputting exactly in spec between 1000 and 2000; it's probably not but should be close enough
doPWM();
//Serial.print("CH3:"); Serial.println(rc_values[RC_CH3]);
//delay(200);
}
void doPWM() {
//1KHz PWM signal means beginning a new pulse every 1000 microseconds or 1 millisecond
//then we just vary the length of the pulse between 0 and 1000 microseconds
unsigned long microseconds = micros();
if(microseconds - lastPwmStart >= 1000) { //begin new pulse
lastPwmStart = microseconds;
digitalWrite(pwmPin, HIGH);
} else {
int targetLength = percentage * 10; //0 - 100 times 10 will be 0 - 1000
if(microseconds - lastPwmStart >= targetLength) { //reached the target pulse length, time to turn off the pin
digitalWrite(pwmPin, LOW);
}
}
}