I will look at it again. But this function thing makes no sense to me to save scan time. Interrupts seem better, but I have no clue as to how to do it and dont understand most of the code at all.
// Train Controller V1.1
const byte MotorVoltagePin = A0; // Motor Voltage via 0-25vdc divider to 0-5vdc
const byte CabLedPin = 2; // Cab Light LED
const int threshold = 400; // Motor Voltage at which the LED goes off
const byte encoderPin = 3; // the pin that the encoder is attached to
const byte FanRelayPin = 3; // the pin that the Relay is attached to
int encoderCounter = 0; // counter for the number of encoder stripes
int encoderState = 0; // current state of the encoder
int lastEncoderState = 0; // previous state of the encoder
void setup()
{
// initialize the LED pin as an output:
pinMode(CabLedPin, OUTPUT);
// initialize the Encoder pin as an input:
pinMode(encoderPin, INPUT);
// initialize the Relay as an output:
pinMode(FanRelayPin, OUTPUT);
// initialize serial communication:
Serial.begin(9600);
}
void loop()
{
DoCabLight();
DoChuffStuff();
}
void DoCabLight()
{
if (MotorIsOn())
{
digitalWrite(CabLedPin, HIGH);
}
else
{
digitalWrite(CabLedPin, LOW);
}
}
void DoChuffStuff()
{
if (MotorIsOn())
{
// Chuff Logic
encoderState = digitalRead(encoderPin);
// compare the encoderState to its previous state
if (encoderState != lastEncoderState)
{
// if the state has changed, increment the counter
if (encoderState == HIGH)
{
// if the current state is HIGH then the encoder went from off to on:
encoderCounter++;
Serial.println("on");
Serial.print("number of encoder pulses: ");
Serial.println(encoderCounter);
}
else
{
// if the current state is LOW then the encoder went from on to off:
Serial.println("off");
}
// Delay a little bit to avoid bouncing
delay(50);
}
// save the current state as the last state, for next time through the loop
lastEncoderState = encoderState;
// turns on the RELAY every four pulses by checking the modulo of the encoder counter.
// The modulo function gives you the remainder of the division of two numbers:
if (encoderCounter % 4 == 0)
{
digitalWrite(FanRelayPin, HIGH);
}
else
{
digitalWrite(FanRelayPin, LOW);
}
}
else
{
digitalWrite(FanRelayPin, LOW);
}
}
bool MotorIsOn()
{
int MotorVoltage = analogRead(MotorVoltagePin);
// if the analog value is high enough, motor has power
return MotorVoltage > threshold;
}
Saving scan time isn't the purpose, in fact, it ever so slightly degrades scan time because of the overhead involved. It's to compartmentalize things so all the gory details aren't in loop(), just a series of function calls. This is to aid readability, organization, troubleshooting, modification, etc.
Lots of PLCs these days have a subroutine call in the instruction set. Functions are to C++ what JSRs are to a PLC.
Thank you very much. I still can’t wrap my head around it though. I know I should be happy you did the work for me, but it really makes me upset that I can’t learn a new trick. The “click” moment just hasn't happened.......
Doing the headlight dim then bright based on motor voltage should be easy, but I can’t see where in the code to add it, let alone how to really do it. Copy and pasting code was easy, but as you pointed out, it’s going to be slow.
// Train Controller V3.0
const byte MotorVoltagePin = A0; // Motor Voltage via 0-25vdc divider to 0-5vdc
const byte CabLedPin = 2; // Cab Light LED
const int threshold = 400; // Motor Voltage at which the LED goes off
const byte encoderPin = 3; // the pin that the encoder is attached to
const byte FanRelayPin = 4; // the pin that the Relay is attached to
const byte HeadlightPin = A1; // the pin the headlight is attached to
int encoderCounter = 0; // counter for the number of encoder stripes
int encoderState = 0; // current state of the encoder
int lastEncoderState = 0; // previous state of the encoder
void setup()
{
// initialize the LED pin as an output:
pinMode(CabLedPin, OUTPUT);
// initialize the Encoder pin as an input:
pinMode(encoderPin, INPUT);
// initialize the Relay Pin as an output:
pinMode(FanRelayPin, OUTPUT);
// initialize serial communication:
Serial.begin(9600);
}
void loop()
{
DoCabLight();
DoChuffStuff();
DoHeadlight();
}
void DoCabLight()
{
if (MotorIsOn())
{
digitalWrite(CabLedPin, HIGH);
}
else
{
digitalWrite(CabLedPin, LOW);
}
}
void DoHeadlight()
{
if (MotorIsOn())
{
analogWrite(HeadlightPin, 1023);
}
else
{
analogWrite(HeadlightPin, 600);
}
}
void DoChuffStuff()
{
if (MotorIsOn())
{
// Chuff Logic
encoderState = digitalRead(encoderPin);
// compare the encoderState to its previous state
if (encoderState != lastEncoderState)
{
// if the state has changed, increment the counter
if (encoderState == HIGH)
{
// if the current state is HIGH then the encoder went from off to on:
encoderCounter++;
Serial.println("on");
Serial.print("number of encoder pulses: ");
Serial.println(encoderCounter);
}
else
{
// if the current state is LOW then the encoder went from on to off:
Serial.println("off");
}
// Delay a little bit to avoid bouncing
delay(50);
}
// save the current state as the last state, for next time through the loop
lastEncoderState = encoderState;
// turns on the RELAY every four pulses by checking the modulo of the encoder counter.
// The modulo function gives you the remainder of the division of two numbers:
if (encoderCounter % 4 == 0)
{
digitalWrite(FanRelayPin, HIGH);
}
else
{
digitalWrite(FanRelayPin, LOW);
}
}
else
{
digitalWrite(FanRelayPin, LOW);
}
}
bool MotorIsOn()
{
int MotorVoltage = analogRead(MotorVoltagePin);
// if the analog value is high enough, motor has power
return MotorVoltage > threshold;
}
There is headlight powered by an existing controller on the train. 16vac from a FET. I’d like to sence that via a digital pin to enable the headlight logic in the Arduino.
The chuff code should always run as it provides data to the sound system as to when to make the chuff sound. But the existing controller has a smoke unit FET 18vac to supply power to the smoke unit. I’d like to be able to control the fan output with a digital input.
The chuff may need to turn on and off the fan for longer periods when moving slow and faster when moving faster.
I haven’t tested it yet, I’m breadboarding it soon.
The radio receiver/ speed controller has a bridge rectifier on it, speed is from a tape encoder strip picked up with a IR led, receiver pair usually with the older controller. The newer speed controller used back emf to do cruise control load based speed control.