Phil_G wrote: 04 Jan 2021, 18:08
Your modification prevents any ppm generation for four seconds Max
You need to do it on a frame-gated basis which is how the inactivity warning works.
It's further complicated by the multiplexed buzzer and button input...
I have posted 2, 3 and 4 channel versions, including rudder/throttle... all work perfectly
Cheers
Phil
Hi Mike,
I revised the entire sketch for my specific purpose, one of the things I did was to split the combined buzzer and s/c button, P1 is now the button and P2 the buzzer.
I did test the whole thing without a buzzer installed (or its led replacement), and all was well. I did not test the inactivity timer, so I don't know if that works or not. But that part is exactly the same as Phil's original (yes Phil, I will add a source reference.....), except maybe for the channel assignment.
This is my code. I commented the part about the reversing check out since I did revise that to add an audible signal (the Webra has a non-centering lever for rudder, so you could be reversing inadvertently), and I wanted to be sure that it is not the culprit of my current trauma..
Cheers,
Max.
Code: Select all
// Simple 2 channel propo encoder for DigiSpark ATTiny85, for Rudder&Throttle channels in a converted Webra Picco transmitter
// A2=throttle, A3=rudder
// Calibrate button is push-to-make in this version, alternate use is to set/reset throttle timeout.
// REMOVE THE SCHOTTKY DIODES ON D3 & D4, the pullup on P3 and either LED or LED Resistor (they flick off easily with a watchmakers screwdriver)
// Connections:
// Pots wired between ground and regulated 5v from the Digispark
// A2(P4)=throttle wiper, A3(P3)=rudder wiper, P2=buzzer, P1=calibrate button, P0=PPM out.
// Rudder pot calibration, hold button in, switch on, still holding button move pot to extremes, hold button.
// Centralise spot including throttle, release button.
// Servo reversing by moving Rudder pot to any end on power up (saved to flash).
// Adapted for Gerard's Webra Picco Tx conversion. Positive mark pulses ppm for Frsky DHT module.
static int ppm = 0, button = 1, buzzer = 2; // D1 is calibrate & timeout set/reset button
int ch, ppmPulse = 300, neutralPulse, raw, calibrated = 1, RudHi = 0, RudLo = 1023, RudMid = 512;
int chtemp, ch0val, channel[] = {0, 0, 0, 0, 0, 0, 8000}; // last is used for sync
byte tlock = 1, RudReverse = 0;
unsigned int inact = 0;
#define INACTFRAMES 30000 // inactivity alarm, 30,000 x 20ms frames is 10 minutes
#define full_n -500 // full negative deflection of sticks
#define full_p +500 // full positive deflection of sticks
#include <EEPROM.h>
void setup() {
OSCCAL = 96; // Digisparks can vary in speed, make larger if timings too long.
noInterrupts();
pinMode(button, INPUT_PULLUP);
pinMode(buzzer, OUTPUT);
pinMode(ppm, OUTPUT);
while (digitalRead(button) == 0) { // calibrate sticks by holding button, (make-contact to GND)
calibrated = 0;
raw = analogRead(3); // read rudder (A3) input
if (raw > RudHi) RudHi = raw;
if (raw < RudLo) RudLo = raw;
RudMid = raw; // save neutral of rudder stick as button is released
} // calibrate button released
if (calibrated == 0) {
// save the calibration values
EEPROMWriteInt(0, RudLo); // eeprom location 0 (decimal)
EEPROMWriteInt(2, RudMid); // eeprom location 2 (decimal)
EEPROMWriteInt(4, RudHi); // eeprom location 4 (decimal)
calibrated = 1; // flag as calibrated
}
// load the saved calibration values
RudLo = EEPROMReadInt(0); // eeprom location 0 (decimal)
RudMid = EEPROMReadInt(2); // eeprom location 2 (decimal)
RudHi = EEPROMReadInt(4); // eeprom location 4 (decimal)
// load saved rudder channel reversal from eeprom location 6 (decimal), only last bit is considered
RudReverse = EEPROM.read(6) & 1; // (bitwise AND with B00000001: set bits 1-7 to 0, leave bit0 as is)
// check for rudder reversing, stick over on power-up.
/* channel[1] = map(analogRead(3), RudLo, RudHi, full_n, full_p);
if (channel[1] > full_p - 50 || channel[1] < full_n + 50) {
while (digitalRead (button) == 1) digitalWrite (buzzer,HIGH); // buzzer sounds to avoid inadvertent reversal,
digitalWrite (buzzer,LOW); // continue by pressing button, switch Tx off to abort
RudReverse ^= B0000001; // flip bit0 of byte
EEPROM.write(6, RudReverse);
}
*/
neutralPulse = 1500 - ppmPulse;
for (int x = 0; x<2; x++) {
delay (1000);
digitalWrite (buzzer,HIGH);
delay (1000);
digitalWrite (buzzer,LOW);
}
}
void loop() {
raw = analogRead(2); // read throttle pot wiper to A2
channel[0] = map (raw, 0, 1023, full_n, full_p);
raw = analogRead(3); // read rudder pot wiper to A3
if (raw > RudMid) channel[1] = map (raw, RudMid, RudHi, 0, full_p);
else channel[1] = map (raw, RudLo, RudMid, full_n, 0);
ch0val = channel[1]; // used by inactivity timer
channel[2] = 0; // channel 2 neutral
channel[3] = 0; // channel 3 neutral
channel[4] = 0; // channel 5 neutral
channel[5] = 0; // channel 6 neutral
channel[6] = 0; // 7th element is sync
// soft throttle lock, throttle can't be opened until it has been closed first
if (channel[0] < full_n + 50) tlock = 0;
if (tlock) channel[0] = full_n;
// rudder channel reversal
if (RudReverse == 1) channel[1] = - channel[1];
// frame formatting
for (int ch = 0; ch < 6; ch++) {
channel[ch] = constrain(channel[ch], full_n, full_p);
channel[ch] += neutralPulse;
channel[6] += channel[ch];
}
channel[6] = 15000 - channel[6]; // CHECK, SHOULD BE 20000 - 7*PPMPULSE - CHANNEL [6]
//send ppm frame, last channel holds sync value
for (int ch = 0; ch < 7; ch++) {
digitalWrite(ppm, HIGH);
delayMicroseconds(ppmPulse);
digitalWrite(ppm, LOW);
delayMicroseconds(channel[ch]);
}
// inactivity timer. 10 mins is approx 30000 frames.
if (ch0val < -100 || ch0val > 100) { // moving rudder resets timer start
inact = 0;
}
if (++inact > INACTFRAMES) {
if (bitRead(inact, 3) == 1 && bitRead(inact, 5) == 1) {
digitalWrite(buzzer, HIGH);
}
else {
digitalWrite(buzzer, LOW);
if (digitalRead(button) == 0) inact = 0; // Push button to stop alarm
}
}
}
// This function will write a 2 byte integer to the eeprom at the specified address and address + 1
void EEPROMWriteInt(int p_address, int p_value)
{
byte lowByte = p_value % 256;
byte highByte = p_value / 256;
EEPROM.write(p_address, lowByte);
EEPROM.write(p_address + 1, highByte);
}
//This function will read a 2 byte integer from the eeprom at the specified address and address + 1
unsigned int EEPROMReadInt(int p_address)
{
byte lowByte = EEPROM.read(p_address);
byte highByte = EEPROM.read(p_address + 1);
return lowByte + highByte * 256;
}