//By D.Weerasinghe COTM
#define noOfInputs 5 // Sum of inputs and outputs should be less than 10
#define noOfOutputs 5 // Sum of inputs and outputs should be less than 10
#define noOfAnalogInputs 3 // No of analog inputs Used in the program
#define noOfMemorybits 5 // can declare any number
#define noOfTimers 3 // No of timers defined
#define printPindetails 0 // 1 to print 0 to disable print
#define printInputImage 0 // 1 to print 0 to disable print
#define printOutputImage 0 // 1 to print 0 to disable print
#define PrintScanCycleTiming 0 // 1 to print 0 to disable print
#define printTimers 0 // Print the timers assigned
#define printTimeVal 1 // print the time value in ms.
#define printTimeValInterval 500 // print interval in milliseconds
/*
inputs and outputs pind should use in this way.
#define input1Pin 3
#define input2Pin 4
#define input3Pin 5
#define input4Pin 6
#define output1Pin 13
#define output2Pin 12
#define output3Pin 11
#define output4Pin 10
*/
unsigned long TimerDetailPrintIntervalTicks =0; // For TimerUpdate
bool I[noOfInputs]; //inputs
bool O[noOfOutputs]; // outputs
bool M[noOfMemorybits]; //memorybit
bool T[noOfTimers]; // Timer bit
bool TM[noOfTimers]; // Timer Mode 0 for ondelay 1 for off delay
bool TE[noOfTimers]; // Timer Enable bit (timer Start when high)
bool TEE[noOfTimers]; // Timer started and First cycle passed indicator
byte TS[noOfAnalogInputs]; // Timer set value in 100ms multiples
int AI[noOfAnalogInputs]; // Analog inputs
unsigned long timerval[noOfTimers]; // millis used by each timer
unsigned int TV[noOfTimers]; //timer Set Value in ms
int scanCycleNumber = 0;
void declareInputOutputs();
void scanInputs();
void UpdateOutputs();
void printTimersDetails();
void declareTimers();
void UpdateTimers();
void setup() {
//Declaration of Inputs and Outputs
if(printPindetails || printInputImage || printOutputImage || printTimers || printTimeVal )Serial.begin(9600);
declareInputOutputs();
declareTimers();
TS[0] = 20; // Timer T0 Set value in 100 ms
TM[0] = 0; // T0 set to on delay
TS[1] = 30; // Timer Set value in 100 ms
TM[1] = 0; // T2 set to on delay
TS[2] = 5; // Timer Set value in 100 ms
TM[2] = 1; // T3 set to off delay
}
void loop() {
//Serial.println(millis() ); // for experimental determination of Cycle time Adjustment
//if(PrintScanCycleTiming) printscancycle("Start") ;
scanInputs(); // Scan Inputs and prepare Input Image
UpdateTimers(); // Update timer values and bits
// Write PLC Program Here to calculate the outputs based on input image
// Timer Test
TE[0] = I[0]; // T0 Enabled by I0
TE[1] = I[1]; // T0 Enabled by I2
TE[2] = I[2]; // T0 Enabled by I0
O[0] = T[0]; // output O0 connected to T0
O[2] = T[1]; // output O2 connected to T1
O[3] = T[2]; // output O3 connected to T3
// End Timer Test
//Pulse Timer
/*
TE[0] = I[0] && T[2] ; // T0 Enabled by I0
TE[2] = I[0] && !T[0]; //T2 Enabled when T0 times up
O[0] = T[0]; // Off time by on delay value and On time by off delay value
//O[1] = T[2];
*/
/*
output[0] = input[0];
output[1] = input[1];
output[2] = input[2];
output[3] = input[3];
output[4] = input[4];
*/
/*
output[1] = 0;
delay(500);
output[1] = 1;
delay(1000);*/
UpdateOutputs();
//UpdateOutputs(printOutputImage);
if(PrintScanCycleTiming) printscancycle("End") ;
// void UpdateOutputs(PrintScanCycleTiming,printOutputImage);
scanCycleNumber++;
//Serial.println(millis() ); // for experimental determination of Cycle time Adjustment
}
void declareInputOutputs(){
if(printPindetails)Serial.println("Pins declared as inputs :");
for(int pin = 3; pin<3+ noOfInputs; pin++){
pinMode(pin, INPUT);
if(printPindetails)Serial.println(pin);
}
if(printPindetails)Serial.println();
//if(printPindetails)Serial.println();
if(printPindetails)Serial.println("Pins declared as outputs :");
for(int pin = 13; pin>13 - noOfOutputs; pin--){
pinMode(pin, OUTPUT);
if(printPindetails)Serial.println(pin);
}
if(printPindetails)Serial.println();
//if(printPindetails)Serial.println();
}
void scanInputs(){
if(printInputImage)Serial.println("Input Image:");
for(int pin = 3; pin<3+ noOfInputs; pin++){
I[pin-3] = digitalRead(pin);
}
for(int pin = 3; pin<3+ noOfInputs; pin++){
if(printInputImage){
Serial.print(" input pin");
Serial.print(pin-3);
Serial.print(" Value: ");
Serial.print(I[pin-3]);
}
}
if(printInputImage)Serial.println();
}
void UpdateOutputs(){
if(printOutputImage)Serial.println("Output Image:");
for(int pin = 13; pin>13 - noOfOutputs; pin--){
if(printOutputImage){
Serial.print(" output pin");
Serial.print(13-pin);
Serial.print(" Value: ");
Serial.print(O[13-pin]);
}
}
if(printOutputImage)Serial.println();
for(int pin = 13; pin>13 - noOfOutputs; pin--){
digitalWrite(pin,O[13-pin]);
}
}
void printscancycle(String StartOrEnd ){
int adjustment = 20; //value based on experiment
if (StartOrEnd =="start"||StartOrEnd =="Start") adjustment = 90;//value based on experiment
if(PrintScanCycleTiming){
Serial.print("cycle No: ");
Serial.print(scanCycleNumber);
Serial.print(" ");
Serial.print(StartOrEnd);
Serial.print(" at: ");
Serial.print(millis() + adjustment ); // 24 estimated based on experiment for additional due to print command
Serial.println(" milliseconds");
}
}
void printTimersDetails(){
for (byte timer = 0 ; timer < noOfTimers; timer++){
Serial.print("TE[");
Serial.print(timer);
Serial.print("] : ");
Serial.println(TE[timer]);
Serial.print("TS[");
Serial.print(timer);
Serial.print("] : ");
Serial.println(TS[timer]);
/*
Serial.print("TEE[");
Serial.print(timer);
Serial.print("] : ");
Serial.println(TEE[timer]);
*/
}
}
void declareTimers(){
for (byte timer = 0 ; timer < noOfTimers; timer++){
T[timer] = TM[timer];
}
if(printTimers) printTimersDetails(); /// ***************************
}
void printTimersValues() { //****************************************
for (byte timer = 0 ; timer < noOfTimers; timer++){
Serial.print("TV[");
Serial.print(timer);
Serial.print("] : ");
Serial.println(TV[timer]);
}
}
void UpdateTimers(){ //******************************************
for (byte timer = 0 ; timer < noOfTimers; timer++){
/*
Serial.print(timer);
Serial.println("for loop "); */
if((TE[timer] && !TM[timer]) ||(!TE[timer] && TM[timer])) { // if Timer Enable high Ondelay(TM=0) Start, otherwise offdelay (TM=1) Start
/*Serial.print("Timer ");
Serial.print(timer);
Serial.println(" Entered");*/
if(!TEE[timer]) { // If timer fist time Enabled
timerval[timer] = millis();
TEE[timer] = 1;
/*
Serial.print("Timer ");
Serial.print(timer);
Serial.println(" 1st time Entered"); */
}
else { // when timer running
TV[timer] = round((millis() - timerval[timer])/100) ;
/*
Serial.print("Timer ");
Serial.print(timer);
Serial.println(" other time Entered"); */
}
}
else {
TEE[timer] = 0;
TV[timer] = 0;
T[timer] = TM[timer]; // && TE[timer]
/*
Serial.print("Timer ");
Serial.print(timer);
Serial.println(" else Entered"); */
}
if(TV[timer] > TS[timer]){
T[timer] = !TM[timer] && TE[timer];
}
}
if (millis() - TimerDetailPrintIntervalTicks > printTimeValInterval){
if(printTimeVal) printTimersValues();
if(printTimers) printTimersDetails();
TimerDetailPrintIntervalTicks = millis();
}
}
// PrintScanCycleTiming
// void UpdateOutputs(bool PrintCycleTime, bool printImage){