here is an added bonus...
for Tim Garrod, here is a generic version of the sketch that i showed in the third posting, it will allow you to switch 4 on/off r/c switches using two 3 position switches,
using the following logic in combination with the multi-prop decoding routine from the previous posts, one would have the routines needed to implement a mutli-switch.
/*
Fade
This example shows how to fade an LED on pin 9
using the analogWrite() function.
This example code is in the public domain.
*/
#include <EnableInterrupt.h>
#include <Servo.h>
//the basic function of this sketch is to expand
//two receiver outputs to run 4 servos.
//this allows a 3 position switch to turn on or off
//four different devices, with a latching function.
#define SERVO_IN_PIN_A 2
#define SERVO_IN_PIN_B 3
#define SERVO_OUT_PIN_A 21
#define SERVO_OUT_PIN_B 20
#define SERVO_OUT_PIN_C 19
#define SERVO_OUT_PIN_D 18
#define HIGH_SERVO 1800
#define MID_SERVO 1500
#define LOW_SERVO 1200
#define NEUTRAL_SERVO_HIGH 1600
#define NEUTRAL_SERVO_LOW 1400
int crnt_state_A = 1; // 0 1 2 for three state switch
int prev_state_A = -1;
int crnt_state_B = 1; // 0 1 2 for three state switch
int prev_state_B = -1;
int upper_state_A = 0; // 0 or 1, on or off
int lower_state_A = 0;
int upper_state_B = 0; // 0 or 1, on or off
int lower_state_B = 0;
volatile unsigned long Servo_Val_A;
volatile unsigned long Servo_Val_A_start;
volatile unsigned long Servo_Val_B;
volatile unsigned long Servo_Val_B_start;
//unsigned long serial_time = 0;
Servo servo_A;
Servo servo_B;
Servo servo_C;
Servo servo_D;
// the setup routine runs once when you press reset:
void setup() {
//set up servo timer defaults
Servo_Val_A_start = micros();
Servo_Val_A = MID_SERVO;
Servo_Val_B_start = micros();
Servo_Val_B = MID_SERVO;
//set current default values for servo settings
crnt_state_A = 1; //0, 1, or 2 vals for 3 position switch
prev_state_A = 1;
upper_state_A = 0; // 0 or 1, on or off
lower_state_A = 0;
crnt_state_A = 1; //0, 1, or 2 vals for 3 position switch
prev_state_A = 1;
upper_state_A = 0; // 0 or 1, on or off
lower_state_A = 0;
// set up interrupt for receiver/servo input pin
enableInterrupt(SERVO_IN_PIN_A, readServoA, CHANGE);
enableInterrupt(SERVO_IN_PIN_B, readServoB, CHANGE);
servo_A.attach(SERVO_OUT_PIN_A);
servo_B.attach(SERVO_OUT_PIN_B);
servo_C.attach(SERVO_OUT_PIN_C);
servo_D.attach(SERVO_OUT_PIN_D);
servo_A.writeMicroseconds(LOW_SERVO);
servo_B.writeMicroseconds(LOW_SERVO);
servo_C.writeMicroseconds(LOW_SERVO);
servo_D.writeMicroseconds(LOW_SERVO);
//give the system time to stabilize before we
//start caring about data coming from receiver
delay(3000);
}
// the loop routine runs over and over again forever:
void loop() {
if (Servo_Val_A >= HIGH_SERVO) {
crnt_state_A = 2;
if (crnt_state_A != prev_state_A){
if (upper_state_A == 1) {
upper_state_A = 0;
} else {
upper_state_A = 1;
}
prev_state_A = crnt_state_A;
}
}
if (Servo_Val_A >= NEUTRAL_SERVO_LOW) {
if (Servo_Val_A <= NEUTRAL_SERVO_HIGH) {
crnt_state_A = 1;
prev_state_A = 1;
}
}
if (Servo_Val_A <= LOW_SERVO) {
crnt_state_A = 0;
if (crnt_state_A != prev_state_A){
if (lower_state_A == 1) {
lower_state_A = 0;
} else {
lower_state_A = 1;
}
// lower_state_A = !lower_state_A;
prev_state_A = crnt_state_A;
}
}
if (upper_state_A == 1) {
servo_A.writeMicroseconds(HIGH_SERVO);
}
else
{
servo_A.writeMicroseconds(LOW_SERVO);
}
if (lower_state_A == 1) {
servo_B.writeMicroseconds(HIGH_SERVO);
}
else
{
servo_B.writeMicroseconds(LOW_SERVO);
}
if (Servo_Val_B >= HIGH_SERVO) {
crnt_state_B = 2;
if (crnt_state_B != prev_state_B){
if (upper_state_B == 1) {
upper_state_B = 0;
} else {
upper_state_B = 1;
}
// upper_state_B = !upper_state_B;
prev_state_B = crnt_state_B;
}
}
if (Servo_Val_B >= NEUTRAL_SERVO_LOW) {
if (Servo_Val_B <= NEUTRAL_SERVO_HIGH) {
crnt_state_B = 1;
prev_state_B = 1;
}
}
if (Servo_Val_B <= LOW_SERVO) {
crnt_state_B = 0;
if (crnt_state_B != prev_state_B){
if (lower_state_B == 1) {
lower_state_B = 0;
} else {
lower_state_B = 1;
}
// lower_state_B = !lower_state_B;
prev_state_B = crnt_state_B;
}
}
if (upper_state_B == 1) {
servo_C.writeMicroseconds(HIGH_SERVO);
}
else
{
servo_C.writeMicroseconds(LOW_SERVO);
}
if (lower_state_B == 1) {
servo_D.writeMicroseconds(HIGH_SERVO);
}
else
{
servo_D.writeMicroseconds(LOW_SERVO);
}
}
void readServoA()
{
if (digitalRead(SERVO_IN_PIN_A) == HIGH)
{
Servo_Val_A_start = micros();
}
else
{
Servo_Val_A = (uint16_t)(micros() - Servo_Val_A_start);
}
}
void readServoB()
{
if (digitalRead(SERVO_IN_PIN_B) == HIGH)
{
Servo_Val_B_start = micros();
}
else
{
Servo_Val_B = (uint16_t)(micros() - Servo_Val_B_start);
}
}
i think in the next posting, i will see if i can't write a sketch that drives 12 servo outputs in an attempt to replicate a multi-prop 4+4 decoder that can run 4 servos proportionately, and 8 servos as simple on/off switches.
I think this would be handy, in a way this would allow us to have the type of function that each element of the decoder can be, to be configured on the fly to either be a proportional servo, or a pair of latching servo outputs, or a pair of latching digital outputs (to drive relays) to replicate a 12+2 decoder with servo/digital outputs would require 14 output pins... i will need to check and see if an arduino pro micro can drive that many at once.
another question for those following: would you prefer an application that runs on a separate device, so the arduino needs to be plugged into to configure the decoder, or would you prefer something like a set of buttons or dials on the arduino. one option offers convenience (the dials & buttons method) the other allows for a much higher degree of control (a computer based GUI for setting up the decoder would allow for many more options)