Hi Guys. I like making rc stuff for which I encounter a problem of big sized atmegas. Since I always use my own made nrf based transmitter and receiver and have lot of RC stuff I simply leave the receiver connected to the devices and make a new receiver for another .But this makes me feel bad for atmega328pu because its capabilities are left unused. Hence this time I want to use ATTINY85 for receiver but due to lack of pins I cannot use it for more than 2 channels incase of pwm output since nrf utilises 4pins.
So I want to make ppm output so that a single pin will connect to flight controller and do all but i have never used ppm and not at all familiar .I saw some codes online but they all are using registers which aren't present in attiny .
Can someone please help me in encoding my integer values to ppm signal. A minimum of 6 channels are needed.
In an RC context, PPM is simply the individual PWM channel pulse widths with a very short inactive period, consecutively, with a longer inactive period marking the end of frame.
TheMemberFormerlyKnownAsAWOL:
In an RC context, PPM is simply the individual PWM channel pulse widths with a very short inactive period, consecutively, with a longer inactive period marking the end of frame.
So i guess Servo.writeMicroseconds(1) followed by a gap of 1500microseconds and again Servo.writeMicroseconds(2) should give 1500 reading for a single channel.
But how to set that gap all delay do since i don't have an oscilloscope .
TheMemberFormerlyKnownAsAWOL:
In an RC context, PPM is simply the individual PWM channel pulse widths with a very short inactive period, consecutively, with a longer inactive period marking the end of frame.
That's what I thought but I just looked it up and it seems to be somewhat different.
All of the PPM pulses are 500 microseconds (1/2 millisecond). Only the leading/rising edges are used. The channel 1 signal goes HIGH on the first rising edge. On the second rising edge (1000 to 2000 microseconds later) the channel 1 signal goes LOW and the channel 2 signal goes HIGH. On the third rising edge (1000 to 2000 microseconds later) the channel 2 signal goes LOW and the channel 3 signal goes HIGH, etc. After the fall of the last channel there is a 12 millisecond (or more) gap before the next channel 1 rising edge.
Here is a crude way to do it using delayMicroseconds():
const byte ChannelCount = 6;
const byte PPMPin = 4;
int ChannelValue[ChannelCount]; // Values from 0 to 1000 (pulses from 1000 to 2000 microseconds)
unsigned long StartOfGap = 0;
void setup()
{
digitalWrite(PPMPin, LOW);
pinMode(PPMPin, OUTPUT);
}
void loop()
{
// Put 12 millisecond gap between pulse trains
if (millis() - StartOfGap >= 12)
{
for (byte chan = 0; chan < ChannelCount; chan++)
{
digitalWrite(PPMPin, HIGH);
delayMicroseconds(500);
digitalWrite(PPMPin, LOW);
delay(1000 - 500 + ChannelValue[chan]);
}
digitalWrite(PPMPin, HIGH);
delayMicroseconds(500);
digitalWrite(PPMPin, LOW);
StartOfGap = millis(); // Start the gap timer after the pulses
}
}
johnwasser:
That's what I thought but I just looked it up and it seems to be somewhat different.
All of the PPM pulses are 500 microseconds (1/2 millisecond). Only the leading/rising edges are used. The channel 1 signal goes HIGH on the first rising edge. On the second rising edge (1000 to 2000 microseconds later) the channel 1 signal goes LOW and the channel 2 signal goes HIGH. On the third rising edge (1000 to 2000 microseconds later) the channel 2 signal goes LOW and the channel 3 signal goes HIGH, etc. After the fall of the last channel there is a 12 millisecond (or more) gap before the next channel 1 rising edge.
Here is a crude way to do it using delayMicroseconds():
const byte ChannelCount = 6;
const byte PPMPin = 4;
int ChannelValue[ChannelCount]; // Values from 0 to 1000 (pulses from 1000 to 2000 microseconds)
unsigned long StartOfGap = 0;
With some tweaks from John's code and reading about ppm online ,Here is the final code that worked exactly as wanted.
const byte ChannelCount = 6;
const byte PPMPin = 1 ;
int ChannelValue[ChannelCount]; // Values from 0 to 1000 (pulses from 1000 to 2000 microseconds)
void setup()
{
digitalWrite(PPMPin, LOW);
pinMode(PPMPin, OUTPUT);
ChannelValue[0]=226;
ChannelValue[1]=321;
ChannelValue[2]=413;
ChannelValue[3]=506;
ChannelValue[4]=600;
ChannelValue[5]=694;
}
long st,et;
void loop()
{
st=micros();
for (byte chan = 0; chan < ChannelCount; chan++)
{
digitalWrite(PPMPin, HIGH);
delayMicroseconds(400);//500
digitalWrite(PPMPin, LOW);
delayMicroseconds(500+ChannelValue[chan]);
}
digitalWrite(PPMPin, HIGH);
delayMicroseconds(400);
digitalWrite(PPMPin, LOW);
et=micros();
delayMicroseconds(20000-(et-st));
}
However I think there is still some issues due to which I get a little different values thats why in void setup I set channelval[0] to 126 to get 1100 in ppm signal while 321 for 1200 , .etc. I'll setup this with nrf's and then see the response with analog pot values currently the values are constant.
Thanks JOHN and AWOL .
Ill update this thread with the next outcome .
This is awesome but digispark doesn't give support for spi lib nor has its own hence I have to upload tiny core boot loader and then use this all .I don't know will this library work afterwards since its for micronucleus .
I do not understand your question, but I use the RC-Navy libraries with bare Attiny85 (and others) and program them via USBASP. Mixing libraries is always try and error for me, as they may or may not allocate timers or other resources exclusively.