Home | Community | Message Board


This site includes paid links. Please support our sponsors.


Welcome to the Shroomery Message Board! You are experiencing a small sample of what the site has to offer. Please login or register to post messages and view our exclusive members-only content. You'll gain access to additional forums, file attachments, board customizations, encrypted private messages, and much more!

Shop: Original Sensible Seeds High THC Strains   Bridgetown Botanicals CBD Concentrates   Unfolding Nature Unfolding Nature: Being in the Implicate Order   PhytoExtractum Buy Bali Kratom Powder   Kraken Kratom Kratom Capsules for Sale

Jump to first unread post Pages: 1
Offlineshamanamba
The Shaman
Male User Gallery


Registered: 06/15/05
Posts: 1,122
Last seen: 1 month, 17 days
Any Arduino gurus out there wanna help out a noob?
    #26358190 - 12/03/19 12:05 AM (4 years, 1 month ago)

I'm trying to build an Arduino controlled trailer tester for work...

Most if it I have figured out, but I'm having trouble with programming the turn signals.

It's easy enough to get each turn signal to blink individually when their respective button is pressed, but I'm trying to get them both to blink simultaneously when both buttons are pressed or in the "ON" state simultaneously.

That's it. That's all I need to figure out and it's turning out to be a lot more in depth than I thought it would be.

Anyone know how to accomplish this?
Kind thanks in advance :confused:


--------------------
The Shaman


Extras: Filter Print Post Top
Invisiblekoraks
Registered: 06/02/03
Posts: 26,667
Re: Any Arduino gurus out there wanna help out a noob? [Re: shamanamba]
    #26358205 - 12/03/19 12:21 AM (4 years, 1 month ago)

Should be pretty easy.

Can you post us the electrical schematic and the code you're using?

Personally if I were doing this, I wouldn't really use dedicated buttons for individual lights (otherwise the Arduino doesn't make sense really and could easily be omitted), but rather make a menu structure and interact with the user through one or more multi-purpose buttons and/or rotary encoders and a simple display (character or lcd). Then program the different functions as software routines that switch the different lights using relays or mosfets driven from the Arduino's GPIO ports using small-signal driver mosfets (e.g. 2n7000).


Extras: Filter Print Post Top
Offlineshamanamba
The Shaman
Male User Gallery


Registered: 06/15/05
Posts: 1,122
Last seen: 1 month, 17 days
Re: Any Arduino gurus out there wanna help out a noob? [Re: koraks]
    #26359634 - 12/03/19 05:23 PM (4 years, 1 month ago)

first off, thank you so much for jumping in here! I'm truly grateful!

I'm mainly going to be using this with my smart phone once everything's said and done, but I also want it to have a set of physical buttons to use the basic on/off functions for each circuit on the trailer without the need for the phone app. This is also a device my employees are going to be borrowing to test their jobs too, so the physical buttons are sort of a must...

right now I have the turn signal flashers running through a crudely written interrupt, and they both flash, but in strange sequences and rhythms, unlike the steady synchronized simultaneous blink I was expecting. will post the code and pics of the project when I get back to my office.


--------------------
The Shaman


Extras: Filter Print Post Top
Invisiblekoraks
Registered: 06/02/03
Posts: 26,667
Re: Any Arduino gurus out there wanna help out a noob? [Re: shamanamba]
    #26360247 - 12/04/19 12:28 AM (4 years, 1 month ago)

Yeah, I think the schematic and code should clarify what you're describing. I understand what you're trying to do and there are many ways to skin a cat, so let's see which route you have chosen and if I can give some additional hints.

An interrupt routine is not strictly necessary, but when reading button statuses, I personally usually use interrupts as well, and it's certainly not wrong. However, I think that on the Arduino, the number of interrupt pins is limited (only 2 IIRC) so it may be difficult to link all the buttons to an interrupt (again, it can be done, e.g. using an MCP23017 GPIO port expander). I'm not sure what you mean by driving the blinkers through an interrupt, so that's why a schematic would be useful to get a good understanding of what you're trying to say.


Extras: Filter Print Post Top
Offlineshamanamba
The Shaman
Male User Gallery


Registered: 06/15/05
Posts: 1,122
Last seen: 1 month, 17 days
Re: Any Arduino gurus out there wanna help out a noob? [Re: koraks]
    #26361608 - 12/04/19 06:33 PM (4 years, 1 month ago)

Well there's only a left and right turn signal so I only need two interrupt pins.

I don't exactly have a schematic, but here's a pic of the project...





I only have the outputs hooked up to the relay boards at the moment. Waiting for a six button membrane switch to come in the mail. for the time being, I've just been grounding the input pins on the breadboard to test.




Code as follows....



//TM = Tail and Marker Lights
//LT = Left Turn Signal
//RT = Right Turn Signal                             
//EB = Electric Brakes
//TPC= Trailer Power Circuit (for charging batteries/Running Accessories I.E. lights,fans,pumps...)
//BU = Back Up or Reverse lamps(Also sometimes powers hydraulic solenoids or back up beepers)

#include <TimerOne.h>          //Library for interrupt

String LTBlinkState="OFF";     
String RTBlinkState="OFF";

// Input pins from physical buttons
int TMIn=4;
int LTIn=2;
int RTIn=3;
int EBIn=5;
int TPCIn=6;
int BUIn=7;


//Six channels of analog read to be added later on analog pins for checking the trailer connectors on vehicles


// Output pins to relay boards
// TM,LT,RT and BU outs go to dual 10 amp relays
// EB and TPC outs each go to single 30 amp relays
int TMOut=8;   
int LTOut=9;
int RTOut=10;
int EBOut=11;
int TPCOut=12;
int BUOut=13;


int TMRead;
int LTRead;
int RTRead;
int EBRead;
int TPCRead;
int BURead;



void setup() {
 

pinMode (TMIn,INPUT_PULLUP);
pinMode (LTIn,INPUT_PULLUP);
pinMode (RTIn,INPUT_PULLUP);
pinMode (EBIn,INPUT_PULLUP);
pinMode (TPCIn,INPUT_PULLUP);
pinMode (BUIn,INPUT_PULLUP);

pinMode (TMOut,OUTPUT);
pinMode (LTOut,OUTPUT);
pinMode (RTOut,OUTPUT);
pinMode (EBOut,OUTPUT);
pinMode (TPCOut,OUTPUT);
pinMode (BUOut,OUTPUT);
}

void loop() {
 

TMRead=digitalRead(TMIn);
LTRead=digitalRead(LTIn);
RTRead=digitalRead(RTIn);
EBRead=digitalRead(EBIn);
TPCRead=digitalRead(TPCIn);
BURead=digitalRead(BUIn);

if (TMRead==0) {
  digitalWrite(TMOut,LOW);
  }
if (TMRead==1) {
  digitalWrite(TMOut,HIGH);
}

if (LTRead==1) {
  digitalWrite(LTOut,HIGH);
  }
if (LTRead==0) {
Timer1.initialize(300000);
Timer1.attachInterrupt (TSBlink); 

}

if (RTRead==1) {
  digitalWrite(RTOut,HIGH);
  }
if (RTRead==0) {
Timer1.initialize(300000);
Timer1.attachInterrupt (TSBlink);

}


if (EBRead==1) {
  digitalWrite(EBOut,LOW);
  }
if (EBRead==0) {
  digitalWrite(EBOut,HIGH);
}

if (TPCRead==1) {
  digitalWrite(TPCOut,LOW);
  }
if (TPCRead==0) {
  digitalWrite(TPCOut,HIGH);
}

if (BURead==0) {
  digitalWrite(BUOut,LOW);
  }
if (BURead==1) {
  digitalWrite(BUOut,HIGH);
}

}



// Turn Signal blink Interrupt
void TSBlink () 

{

if (LTBlinkState == "ON")


  digitalWrite (LTOut, LOW);
  LTBlinkState="OFF";
  return;
}


if (LTBlinkState == "OFF")

{
  digitalWrite (LTOut, HIGH);
  LTBlinkState="ON";
}


if (RTBlinkState == "ON")

{
  digitalWrite (RTOut, LOW);
  RTBlinkState="OFF";
  return;
}

if (RTBlinkState == "OFF")

{
  digitalWrite (RTOut, HIGH);
  RTBlinkState="ON";
}

}


--------------------
The Shaman


Extras: Filter Print Post Top
Offlineshamanamba
The Shaman
Male User Gallery


Registered: 06/15/05
Posts: 1,122
Last seen: 1 month, 17 days
Re: Any Arduino gurus out there wanna help out a noob? [Re: shamanamba]
    #26362035 - 12/04/19 11:55 PM (4 years, 1 month ago)

I FIGURED IT OUT!

rewrote the void loop as follows:


void loop() {

Timer1.initialize(300000);

TMRead=digitalRead(TMIn);
LTRead=digitalRead(LTIn);
RTRead=digitalRead(RTIn);
EBRead=digitalRead(EBIn);
TPCRead=digitalRead(TPCIn);
BURead=digitalRead(BUIn);


if (LTRead==0)
{
Timer1.attachInterrupt (TSBlink);
}
else
{
digitalWrite (LTOut,HIGH);
}



if (RTRead==0)
{
Timer1.attachInterrupt (TSBlink);
}
else 
{
digitalWrite (RTOut,HIGH);
}


if (TMRead==0)
{
  digitalWrite(TMOut,LOW);
}
else
{
  digitalWrite(TMOut,HIGH);
}


if (EBRead==1)
{
  digitalWrite(EBOut,LOW);
}
else
{
  digitalWrite(EBOut,HIGH);
}



if (TPCRead==1)
{
  digitalWrite(TPCOut,LOW);
}
else
{
  digitalWrite(TPCOut,HIGH);
}

if (BURead==0)
{
  digitalWrite(BUOut,LOW);
}
else
{
  digitalWrite(BUOut,HIGH);
}

}




// Turn Signal blink Interrupt
void TSBlink () 
{

if (LTBlinkState == "ON")

  digitalWrite (LTOut, LOW);
  LTBlinkState="OFF";

}

if (RTBlinkState == "ON")
{
  digitalWrite (RTOut, LOW);
  RTBlinkState="OFF";
  return;
}



if (LTBlinkState == "OFF")
{
  digitalWrite (LTOut, HIGH);
  LTBlinkState="ON";
}

if (RTBlinkState == "OFF")
{
  digitalWrite (RTOut, HIGH);
  RTBlinkState="ON";
}

}


--------------------
The Shaman


Extras: Filter Print Post Top
Invisiblekoraks
Registered: 06/02/03
Posts: 26,667
Re: Any Arduino gurus out there wanna help out a noob? [Re: shamanamba]
    #26362672 - 12/05/19 10:12 AM (4 years, 1 month ago)

Good job, nice to see you've got it to work!

Like I said, there are many ways to skin a cat and yours is one of them. In terms of code, there are many ways to do it more efficiently, but like I said, the most important thing is that it works the way it is.

Of course once you add the WiFi functionality to it (looks like you'll be interfacing the Arduino with your phone using WiFi) you will have to change some of the code to get the remote commands to also work, but as you have gotten this far, you'll figure out the rest as well, I'm sure.

One issue I'd be inclined to fix is that of bounce of the switches. You may not notice it, but as you press a momentary switch, it's not a clean 'off-on' state, but rather a pretty noisy sequence of 'off-on-off-on-off-on' in whatever random order and timing that happens to present itself. Mind you, all this bouncing around (hence the term 'bounce') happens within a few milliseconds. I usually solve this by basically reading a change from off to on using an interrupt and then only act upon it if the on signal persists after, say, 50 ms.

If you don't include this bounce behavior, you may get the issue that as your Arduino cycles through its main loop, it rapidly turns a relay on and off several times in the timeframe of a few milliseconds. You probably haven't noticed this as your relays are likely too slow to drop off - effectively debouncing the switch this way. There may be issues with reactive currents in the relay coil however (as the mosfet that is probably driving the relay will definitely switch on and off fast enough to keep up with the bouncing) and that may or may not blow up the mosfet driver at some point. Since it's likely protected by a counter-connected diode to catch this current, no problem necessarily has to emerge, unless the bouncing persists long enough to blow up the diode and then the mosfet. Again, it's not a certainty, perhaps it's not even likely, but personally I'd prefer to prevent the issue altogether by properly debouncing the switch.

One more thing to think about is that you may want to include the possibility to toggle the lights (press switch to turn light on, press again to turn it off again) so you can have multiple lights on at the same time. This will make it easier to track down possible grounding issues in the wiring of the trailers. You know how the tail lights of vehicles sometimes blink along with the blinkers due to grounding or wiring issues. This is often not immediately apparent as long as only one light is on at the same time, but it becomes painfully visible once the entire Christmas tree at the rear lights up.

Just a few thoughts that you can take or leave as you desire; again, definitely do it the way it works best for you!


Extras: Filter Print Post Top
Invisiblekoraks
Registered: 06/02/03
Posts: 26,667
Re: Any Arduino gurus out there wanna help out a noob? [Re: koraks]
    #26362791 - 12/05/19 11:13 AM (4 years, 1 month ago)

One more thing btw:
Quote:

//Six channels of analog read to be added later on analog pins for checking the trailer connectors on vehicles



Just to make sure, but you probably realize that you don't want to put the 12V bus of a vehicle on a port of the Arduino, for instance if you would want to measure the onboard voltage to check connections etc. In case you consider something like that, use a voltage divider (two resisters of appropriate values) so that the Arduino never sees more than 5V on the ADC port you're using, and also protect that port with e.g. a 4.7V zener diode for unexpected voltage spikes.


Extras: Filter Print Post Top
Offlineshamanamba
The Shaman
Male User Gallery


Registered: 06/15/05
Posts: 1,122
Last seen: 1 month, 17 days
Re: Any Arduino gurus out there wanna help out a noob? [Re: koraks]
    #26363612 - 12/05/19 06:10 PM (4 years, 1 month ago)

Thank you for all the insight!

I've built several trailer testers before but they're all completely 12v switches and relays with a volt/amp meter and light board display. I wanted to make something that would put the display and controls on my phone so I wouldn't have to run back and forth to the box from the back of the trailer and also so I could test the truck and not have to strain to look back at the box at the rear of the truck while I operate the controls from the drivers seat all the way up front.

This project is still in it's infancy and is serving as my introduction to 5v systems, microcontrollers and programming. I do intend to add coding for toggle on/off push buttons and debounce. I believe the relay boards have optoisolators so the arduino should be safe. And I learned the hard way about voltage division on the 12v inputs...

:derp:

Already fried an uno!

I'm really interested to know how you would code the turn signals if you wouldn't mind elaborating!

Is it ok if I continue to post back to this thread for your advice as I move along with it? It's certainly a slow moving thing that I fit in little bits of time for between jobs.


--------------------
The Shaman


Extras: Filter Print Post Top
Offlineshamanamba
The Shaman
Male User Gallery


Registered: 06/15/05
Posts: 1,122
Last seen: 1 month, 17 days
Re: Any Arduino gurus out there wanna help out a noob? [Re: shamanamba]
    #26363977 - 12/05/19 10:02 PM (4 years, 1 month ago)

I feel like I really cleaned it up and got it to where it'll work with the membrane switch when it arrives in the mail! I'll be working on the analog read pins and getting bluetooth all sorted out some other day. its time for me to go to bed lol check it out whenever you get a chance!




//TM = Tail and Marker Lights
//LT = Left Turn Signal
//RT = Right Turn Signal                             
//EB = Electric Brakes
//TPC= Trailer Power Circuit (for charging batteries/Running Accessories I.E. lights,fans,pumps...)
//BU = Back Up or Reverse lamps(Also sometimes powers hydraulic solenoids or back up beepers)

#include <TimerOne.h>          //Library for interrupt

String LTBlinkState="OFF";     
String RTBlinkState="OFF";

const int TMIn=4;        // Input pins from physical buttons
const int LTIn=2;
const int RTIn=3;
const int EBIn=5;
const int TPCIn=6;
const int BUIn=7;

const int TMOut=8;      // Output pins to relay board 
const int LTOut=9;
const int RTOut=10;
const int EBOut=11;
const int TPCOut=12;
const int BUOut=13;

int TMIState = 0;
int LTIState = 0;
int RTIState = 0;
int EBIState = 0;
int TPCIState = 0;
int BUIState = 0;

int TMOState;
int LTOState;
int RTOState;
int EBOState;
int TPCOState;
int BUOState;

int lastTMIState = LOW;
int lastLTIState = LOW;
int lastRTIState = LOW;
int lastEBIState = LOW;
int lastTPCIState = LOW;
int lastBUIState = LOW;

unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 75;

void setup() {
 

pinMode (TMIn,INPUT_PULLUP);
pinMode (LTIn,INPUT_PULLUP);
pinMode (RTIn,INPUT_PULLUP);
pinMode (EBIn,INPUT_PULLUP);
pinMode (TPCIn,INPUT_PULLUP);
pinMode (BUIn,INPUT_PULLUP);

pinMode (TMOut,OUTPUT);
pinMode (LTOut,OUTPUT);
pinMode (RTOut,OUTPUT);
pinMode (EBOut,OUTPUT);
pinMode (TPCOut,OUTPUT);
pinMode (BUOut,OUTPUT);

digitalWrite (TMOut,TMOState);
digitalWrite (LTOut,LTOState);
digitalWrite (RTOut,RTOState);
digitalWrite (EBOut,EBOState);
digitalWrite (TPCOut,TPCOState);
digitalWrite (BUOut,BUOState); 
}

void loop() {
Timer1.initialize(300000);  //one third of a second timer for turn signal blink

int TMreading = digitalRead(TMIn);    //Tail and marker lights toggle button and debounce
if (TMreading != lastTMIState){
  lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
  if (TMreading != TMIState) {
    TMIState = TMreading;
    if (TMIState == HIGH) {
      TMOState = !TMOState;
    }   
  }
}
digitalWrite (TMOut, TMOState);
lastTMIState = TMreading;
if (TMIState==0) {
  digitalWrite(TMOut,LOW);
}
else{
  digitalWrite(TMOut,HIGH);
}

int LTreading = digitalRead(LTIn);    //Left turn signal toggle button,debounce, and send to STBlink turn signal blink interrupt
if (LTreading != lastLTIState){
  lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
  if (LTreading != LTIState) {
    LTIState = LTreading;
    if (LTIState == HIGH) {
      LTOState = !LTOState;
    }   
  }
if (LTOState==LOW) {
Timer1.attachInterrupt (TSBlink);
}
else {
digitalWrite (LTOut,HIGH);
  }
}
lastLTIState = LTreading;

int RTreading = digitalRead(RTIn);    //Right turn signal toggle button,debounce, and send to STBlink turn signal blink interrupt
if (RTreading != lastRTIState){
  lastDebounceTime = millis();
}

if ((millis() - lastDebounceTime) > debounceDelay) {
  if (RTreading != RTIState) {
    RTIState = RTreading;
    if (RTIState == HIGH) {
      RTOState = !RTOState;
    }   
  }
if (RTOState==LOW) {
Timer1.attachInterrupt (TSBlink); }
else {
digitalWrite (RTOut,HIGH);
}
}
lastRTIState = RTreading;

int EBreading = digitalRead(EBIn);    //Electric Brake toggle button and debounce
if (EBreading != lastEBIState){
  lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
  if (EBreading != EBIState) {
    EBIState = EBreading;
    if (EBIState == HIGH) {
      EBOState = !EBOState;
    }   
  }
}
digitalWrite (EBOut, EBOState);
lastEBIState = EBreading;
if (EBIState==0) {
  digitalWrite(EBOut,LOW);
}
else {
  digitalWrite(EBOut,HIGH);
}

int TPCreading = digitalRead(TPCIn);      //Trailer Power Circuit toggle button and debounce
if (TPCreading != lastTPCIState){
  lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
  if (TPCreading != TPCIState) {
    TPCIState = TPCreading;
    if (TPCIState == HIGH) {
      TPCOState = !TPCOState;
    }   
  }
}
digitalWrite (TPCOut, TPCOState);
lastTPCIState = TPCreading;
if (TPCIState==0) {
  digitalWrite(TPCOut,LOW);
}
else {
  digitalWrite(TPCOut,HIGH);
}

int BUreading = digitalRead(BUIn);      //BackUp or Reverse toggle button and debounce
if (BUreading != lastBUIState){
  lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
  if (BUreading != BUIState) {
    BUIState = BUreading;
    if (BUIState == HIGH) {
      BUOState = !BUOState;
    }   
  }
}
digitalWrite (BUOut, BUOState);
lastBUIState = BUreading;
if (BUIState==0) {
  digitalWrite(BUOut,LOW);
}
else {
  digitalWrite(BUOut,HIGH);
}
}

void TSBlink ()  {                    // Turn Signal blink Interrupt
if (LTBlinkState == "ON") { 
  digitalWrite (LTOut, LOW);
  LTBlinkState="OFF";
}
if (RTBlinkState == "ON") {
  digitalWrite (RTOut, LOW);
  RTBlinkState="OFF";
  return;
}
if (LTBlinkState == "OFF") {
  digitalWrite (LTOut, HIGH);
  LTBlinkState="ON";
}
if (RTBlinkState == "OFF") {
  digitalWrite (RTOut, HIGH);
  RTBlinkState="ON";
  }
}


--------------------
The Shaman


Extras: Filter Print Post Top
Invisiblekoraks
Registered: 06/02/03
Posts: 26,667
Re: Any Arduino gurus out there wanna help out a noob? [Re: shamanamba]
    #26364859 - 12/06/19 11:58 AM (4 years, 1 month ago)

Nice job! Let me see if I can find the time tomorrow to have a take on it. Currently there's a lot of redundancy in the code that can be done away with. I think storing the pin numbers in two arrays and then cycle through them on each loop should do the trick. It'll cut down the number of lines in the code by something like 60%. Easier to maintain that way.


Extras: Filter Print Post Top
Offlineshamanamba
The Shaman
Male User Gallery


Registered: 06/15/05
Posts: 1,122
Last seen: 1 month, 17 days
Re: Any Arduino gurus out there wanna help out a noob? [Re: koraks]
    #26365870 - 12/06/19 08:52 PM (4 years, 1 month ago)

:datass:


I did some studying on arduino arrays at the University of YouTube at Internet and now have sort of a vague idea how this will simplify my code... I'm sorta digesting it all and waiting for that "Ah-HAH!" moment in my sleep at 4am when I have to get out of bed and go to the office attempt to apply it lol any help you can render along the way to that moment is endlessly appreciate!


--------------------
The Shaman


Extras: Filter Print Post Top
Offlineshamanamba
The Shaman
Male User Gallery


Registered: 06/15/05
Posts: 1,122
Last seen: 1 month, 17 days
Re: Any Arduino gurus out there wanna help out a noob? [Re: shamanamba]
    #26365955 - 12/06/19 10:02 PM (4 years, 1 month ago)

side note:

the 30a relay board was giving me problems so I did away with it entirely since my 10a relay board has 16 channels so now the EB circuit goes to 4 10a relays, TPC goes to 4 10a relays, and the rest each go to 2 10a relays, which I feel makes things more efficient by saving space and beefs up the capacity of the two circuits most likely to be shorted out or over loaded (in need of repair)

the 12v power supply I'll be incorporating  into the final build already automatically shuts off by itself if its hooked up to a dead short but I plan to program in another immediate shut off if the ammeter value ever exceeds 30a.


But anyway, thankyou again for all your time and wisdom. I'm gonna be focusing on the housing of this device for a little while just so I don't get burn out on this part of things. Having met you on this forum, I'm sure you understand the eccentric mind :grin:


--------------------
The Shaman


Extras: Filter Print Post Top
Invisiblekoraks
Registered: 06/02/03
Posts: 26,667
Re: Any Arduino gurus out there wanna help out a noob? [Re: shamanamba]
    #26366152 - 12/07/19 01:36 AM (4 years, 1 month ago)

Well, you could store both the input pin numbers and the output pin numbers in arrays and cycle through them in your main loop, and then calling a function to change an output pin state when a button has changed state. For debouncing, you may want to add a third array where you store a timestamp for each input pin. Currently you're using one timestamp for all pins which in practice will work OK unless for some reason several buttons are pressed at the same time, which may result in unpredictable behavior. Again, this may not be a problem in practice, but in terms of the logic in your code, it's not the most elegant solution. In addition, I personally like to use a flag register for each button that stores its previous state for debounce purposes instead of relying on the status of an associated output pin in case of the freak possibility that an output pin for some reason has a different state than you'd expect based on your code (typically due to an unforeseen timing issue in your coding resulting in button presses being missed or registered incorrectly).

Here's what my take on it would look like:
Code:

/*
* Declarations
* Note that all arrays are of the same size
* and defined in such a way that they align with each other
* to reflect the relationships between the values.
*/
byte inputPins[] = {4, 2, 3, 5, 6, 7}; //Input pin numbers for buttons
bool pinPrevState[] = {false, false, false, false, false, false}; //State flag register to store previous state of input pins for debounce purposes
bool pinChanged[] = {false, false, false, false, false, false}; //State flag register to indicate if an input pin has changed
unsigned long pinDebounceTime[] = {0, 0, 0, 0, 0, 0}; //Holder for timestamps for individual button debounce; array size conforms to number of input pins used
byte outputPins[] = {8, 9, 10, 11, 12, 13}; //Output pin numbers for relay board; in same order as associated input pins!
bool isBlinker[] = {false, true, true, false, false, false}; //Register for storing which outputs are blinkers instead of continuous
bool blinkState[] = {false, false, false, false, false, false}; //Register for storing blinker state, allowing toggling of the blinker
bool previousBlinkState[] = {true, true, true, true, true, true}; //Register for storing previousblinker state, allowing toggling of the blinker
unsigned long previousBlink[] = {0, 0, 0, 0, 0, 0}; //Time stamps for last blinker state change
bool outputState[] = {false, false, false, false, false, false}; //Register for storing output pin states

const long debounceTime = 50; //Debounce period in milliseconds
const long blinkInterval = 500; //Blinker interval in milliseconds

void setup() {


}

void loop() {
//No actual code in loop; everything is done in routines
handleButtons(); //Call button handler to read inputs and debounce
setOutputState(); //Set the correct status of output pins depending on input pin state
}

/*
* Button handler routine for reading input button states
* and setting associated output state flags
* Takes: (none)
* Returns: (none)
*/
void handleButtons() {
for (int i = 0; i < sizeof(inputPins)/sizeof(inputPins[0]); i++) {
unsigned long t_now = millis(); //Record current time so we don't have to call millis() several times
//Cycle through each input pin and read its state
bool readState = digitalRead(inputPins[i]);
if (readState != pinPrevState[i]) {
//Input pin state has changed; check if debounce period has lapsed
if (((t_now - pinDebounceTime[i]) > debounceTime) && pinChanged[i]) {
outputState[i] = readState; //Set output pin state flag
pinPrevState[i] = readState; //Reset previous pin state register for next debounce event
pinChanged[i] = false; //Reset flag to indicate that input pin state has changed
}
else if (!pinChanged[i]) {
//Pin status has changed, but flag has not been set, so set the timestamp for beginning the debounce period
//and set the signal flag to indicate we know a pin state change has occurred
pinDebounceTime[i] = t_now;
pinChanged[i] = true;
}
}
else if ((t_now - pinDebounceTime[i]) > debounceTime) {
//Debounce time has elapsed, but pin state has remained the same,
//so reset debounce timestamp, disregarding an apparent bounce event
pinDebounceTime[i] = 0;
pinChanged[i] = false;
}
}
}

/*
* Routine for setting output pins
* Takes: (none)
* Returns: (none)
*/
void setOutputState() {
for (int i = 0; i < sizeof(inputPins)/sizeof(inputPins[0]); i++) {
//Check if the pin is a blinker; if so, call the blink routine
if (isBlinker[i]) {
blinkPin(i); //Call blinker handler
}
else {
//pin is not a blinker; set its state in accordance with the status register
digitalWrite(outputPins[i], outputState[i]);
}
}
}

/*
* Blinker routine; blinks the pin if its associated state is 'true'
* Takes: byte pin ID
* Returns: (none)
*/
void blinkPin(byte pin) {
if (outputState[pin]) {
//Only run the blink routine if the pin flag is set to true
unsigned long t_now = millis();
if ((t_now - previousBlink[pin]) > blinkInterval) {
//Blink interval has elapsed; toggle pin status
digitalWrite(outputPins[pin], blinkState[pin]);
blinkState[pin] = !blinkState[pin];
previousBlink[pin] = t_now;
}
}
else if (blinkState[pin]) {
//Blinker is turned off, but its status is still on, so turn it off
blinkState[pin] = false;
digitalWrite(outputPins[pin], blinkState[pin]);
previousBlink[pin] = 0;
}
}



A few notes:
* Debouncing happens on both button press and button release
* This is probably buggy as fuck, as I have only compiled it but not tested it on a real Arduino. So I'd say use it as an example of an alternative to your approach (mine not being necessarily better or worse; just different and optimized for different things). You'll have to tinker with it in order to get it to work, most likely.
* I opted to essentially use millis() to run the blinker instead of an interrupt, as the timing is non-critical anyway and interrupts can sometimes mess up execution if your program if they are handled in the wrong way (particularly if interrupt handling routines take a bit longer to execute).

In my view the major difference with your code in terms of its core logic is that it uses flag registers (semaphores essentially) to keep track of pin states etc. This makes the code more modular; you could change e.g. the outputState array using whatever additional function besides the button handler (think of your to-be-included bluetooth handler) without having to modify much of the existing code.


Edited by koraks (12/07/19 02:00 AM)


Extras: Filter Print Post Top
Offlineshamanamba
The Shaman
Male User Gallery


Registered: 06/15/05
Posts: 1,122
Last seen: 1 month, 17 days
Re: Any Arduino gurus out there wanna help out a noob? [Re: koraks]
    #26366927 - 12/07/19 01:03 PM (4 years, 1 month ago)

:awenuhuh:


:noyoudidawet:


:pokerawe:


:uh:


:awesurprise:


Yeah this is gonna take me a while to get the hang of... Will fiddle with this and see what happens when I get home!

Thank you!


--------------------
The Shaman


Extras: Filter Print Post Top
Invisiblekoraks
Registered: 06/02/03
Posts: 26,667
Re: Any Arduino gurus out there wanna help out a noob? [Re: shamanamba]
    #26367431 - 12/07/19 05:24 PM (4 years, 1 month ago)

You're welcome. Like I said, it's likely that there are some bugs particularly in the denounce routine because I didn't really teat this code, so it's more intended to show the concept than as a plug & play solution.
I'm sore that you'll figure out how it works. You could even simplify it a bit here and there; this is certainly not yet the most efficient implementation.
One thing I'm not happy with in this version is that on each loop the output ports are being written; it doesn't hurt, but it's kind of unnecessary. An additional array storing the previous state of each output pin and then checking if it has changed before setting the port would take care of this quite quickly.

Also note that this code does not toggle the ports but rather follows your initial implementation  that just mirrors the state of the input pins onto the output pins. A toggle can be easily made by changing one or two lines of the code.


Extras: Filter Print Post Top
Offlineshamanamba
The Shaman
Male User Gallery


Registered: 06/15/05
Posts: 1,122
Last seen: 1 month, 17 days
Re: Any Arduino gurus out there wanna help out a noob? [Re: koraks]
    #28138878 - 01/14/23 01:14 AM (1 year, 13 days ago)

hey koraks! long time! a lot's happened since, eh? I just thought I'd update on this. I had to put the project down for a while but will be getting back to it soon. I didn't quite understand how to implement your code when I first looked over it but I'm reading over this thread again and I think the information is falling into the right neural slots this time lol I ended up doing away with the buttons on the box altogether and set up a wireless control interface from a tablet using an app called RoboRemo and a HC-05 bluetooth adapter for the adruino. I'm about to completely overhaul the UI on the tablet with Unity, which is a whole other thing I'm trying to learn now.

I'm on vacation right now but I'm looking forward to making another attempt to write your code into my device once I get home, as I think it will make things easier to manage on the UI end of things. Anyway, hope you're doing well koraks! I'm hoping you're still around for advice as I work with your code!


--------------------
The Shaman


Extras: Filter Print Post Top
Invisiblekoraks
Registered: 06/02/03
Posts: 26,667
Re: Any Arduino gurus out there wanna help out a noob? [Re: shamanamba]
    #28139484 - 01/14/23 12:56 PM (1 year, 13 days ago)

Cool, nice that you're picking it back up!

Although the code above undoubtedly would still work, I wouldn't write it like that anymore. Instead, I'd model each button as an object and a state machine, so exploiting the possibilities of C++ a little more.

I've done numerous microcontroller projects since then, some in Arduino and some others too such as a few STM8S003 projects (in C, not C++). So I progressed a bit from where I was when I posted the snippet above.

Here's a different implementation for a single button class, but since it's object oriented, you can just instantiate this any number of times, once for each button:

Header file 'button.h'
Code:

/*
* Tactile switch class
*/
#include <Arduino.h>

enum {BTN_IDLE = 0, BTN_HELD_DB = 0xFF, BTN_HELD = 1, BTN_SHORT = 2, BTN_LONG = 3};

const uint8_t DEBOUNCE_MS = 20;
const uint16_t LONG_PRESS_MS = 350;

class button {
public:
void init (uint8_t pin, bool inverted = false);
bool update (); //Call frequently; returns true if button held, short or long press
uint8_t get_state (); //Read button state and reset to BTN_IDLE

private:
uint8_t _pin;
bool _inverted;
unsigned long last_event;
uint8_t state;
uint8_t output_state;
};




Code file 'button.cpp'
Code:


#include "button.h"

void button::init (uint8_t pin, bool inverted) {
_pin = pin;
_inverted = inverted;
pinMode(_pin, INPUT_PULLUP);
}

bool button::update () {
bool pinstate = digitalRead(_pin);
switch (state) {
case BTN_IDLE: {
if (pinstate == _inverted) {
last_event = millis();
state = BTN_HELD_DB;
}
}
break;
case BTN_HELD_DB: {
if (millis() - last_event >= DEBOUNCE_MS) {
//Debounce period expired
output_state = BTN_HELD;
state = BTN_HELD;
return true;
}
if (pinstate != _inverted) {
//Released before debounce period; this was a bounce
state = BTN_IDLE;
return false;
}
}
case BTN_HELD: {
if (millis() - last_event > LONG_PRESS_MS) {
//Still held down after long_press time; register long press
state = BTN_LONG;
output_state = BTN_LONG;
//Note: button is still pressed
return true;
}
if (pinstate != _inverted) {
//Short press; button is released
state = BTN_IDLE;
output_state = BTN_SHORT;
return true;
}
}
break;
case BTN_SHORT: {
//Dummy; should never reach this
state = BTN_IDLE;
return false;
}
break;
case BTN_LONG: {
//Wait for button to release
if (pinstate != _inverted) {
state = BTN_IDLE; //Button released; return to idle
return false;
}
}
break;
}
return false; //Dummy
}

uint8_t button::get_state () {
uint8_t retval = output_state;
if (output_state != BTN_HELD) output_state = BTN_IDLE;
return retval;
}




Place the files above in the folder of your Arduino project where you want to use them. You can then include them using #include.

Usage of the above class would go something like this:
Code:


#include "button.h"

#define PIN_BTN_1 PIN_PB2 //Or whatever GPIO number you want to use

button my_button;

void setup () {
my_button.init(PIN_ROT_BTN);
}

void loop () {
if (my_button.update()) {
switch (my_button.get_state()) {
case BTN_HELD:
//Here goes your code that you want to execute when the button is being pressed and not yet released
break;
case BTN_SHORT:
//Here goes the code you want to execute after the button has been pressed briefly (and consequently released)
break;
case BTN_LONG:
//Here goes the code that runs on a long press; a long press is registered already before the button is released
break;
}
}
}




I didn't compile the above, so apologies if you get errors due to typos etc. It's just to show the principle.

You could modify the example above to have several buttons in an array and then cycle through the array on each loop iteration.
Likewise it's possible to modify the button class code to include features like double click.

Alternatively get any of the ready-made button classes from GitHub and use that. I'm generally too lazy to figure out how someone else implemented their class so usually just write one myself.


Extras: Filter Print Post Top
Jump to top Pages: 1

Shop: Original Sensible Seeds High THC Strains   Bridgetown Botanicals CBD Concentrates   Unfolding Nature Unfolding Nature: Being in the Implicate Order   PhytoExtractum Buy Bali Kratom Powder   Kraken Kratom Kratom Capsules for Sale


Similar ThreadsPosterViewsRepliesLast post
* Arduino for mycology?
( 1 2 all )
Bulldogg757 7,327 25 03/18/17 10:15 AM
by NDStepp84
* To all Arduino/Rasberry Geeks :Question about Sensors CogDog 1,161 8 03/16/14 01:24 PM
by Shroomism
* ARDUINO!! Psilosopherr 1,876 16 01/29/15 04:36 PM
by Sundrop
* I am looing for Arduino and Pic hackers and borad level people... stedenko 1,049 4 10/04/14 01:05 AM
by mycofanaticus
* New arduino nano, possibly faulty? Terrazureus 613 4 05/24/15 11:11 PM
by Terrazureus
* Does anyone here know anything about Arduino? aciddrop 653 3 09/25/14 10:21 AM
by koraks
* PanoBot from Lego Technic and Arduino Annom 2,483 2 10/16/09 01:49 AM
by ShockValue
* wanna go wireless... Anonymous 1,098 11 07/27/04 02:01 PM
by Anonymous

Extra information
You cannot start new topics / You cannot reply to topics
HTML is disabled / BBCode is enabled
Moderator: trendal, automan, Northerner
834 topic views. 0 members, 0 guests and 4 web crawlers are browsing this forum.
[ Show Images Only | Sort by Score | Print Topic ]
Search this thread:

Copyright 1997-2024 Mind Media. Some rights reserved.

Generated in 0.024 seconds spending 0.005 seconds on 12 queries.