Jump to content

Need arduino help

TheRedViper

Hello guys, I have a project where we move a pneumatic thruster along some rails for it to sort pucks. The automatic part went fine, but when I started coding the manual part which requires you not to use any sensors, I started facing a lot of bugs. There's a bug I can't seem to fix, but I kinda know wheres the problem I just dont know where I fucked up. When you press the red button (becomes LOW), the puck loader goes out (done, works fine) and then when you press it again, it should come back (As long as you keep your finger on the button, its retracting, but as soon as you release it, it goes back which is not what its supposed to do as pressing the button should make it retract and it should stay retracted until you press the button again to extend it again). Below you will find the code specific that that button, I removed everything that concerned other buttons and the automatic mode. 

#define POUS_OUT 4

void poussoirManuel()//Function to extend the loader
{
  digitalWrite(POUS_OUT, HIGH);
  Serial.println("Pousse");
}
void poussoirResetManuel()//Function to retract the loader
{
  digitalWrite(POUS_OUT, LOW);
  Serial.println("Reset");
}

void setup() {
  pinMode(POUS_OUT, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  
  static int iNBtnR = 0, iEtatBtnR, iEtatMemBtnR = 0;

  if(digitalRead(SLT_VB)== HIGH)//Switch to put into manual
  {
    iEtatBtnR = (digitalRead(BTN_R) == HIGH);//the current state of the red button
    if((iEtatBtnR != iEtatMemBtnR) && (iEtatBtnR == LOW))//if the memory state of the red button isnt equal to the current state and that it is now LOW
    {
      iNBtnR++;//Verification of statement entry for serial monitor debugging
      Serial.println(iNBtnR);//Verification of statement entry for serial monitor debugging
      poussoirManuel();//Call the function that extends the loader
      iEtatMemBtnR = iEtatBtnR;//Change the memory state
    }
    else if((iEtatBtnR != iEtatMemBtnR) && (iEtatBtnR == HIGH))//if the current state isnt equal to the memory and that the current state is HIGH
    {
      iNBtnR++;//Verification of statement entry for serial monitor debugging
      Serial.println(iNBtnR);//Verification of statement entry for serial monitor debugging
      poussoirResetManuel();//Call the function that retracts the loader
      iEtatMemBtnR = iEtatBtnR;//Change the memory state
    }
  }
}

 

systemePaint.jpg

CPU: Intel Core i9-10900K  MOBO: ROG MAXIMUS XII FORMULA GPU: 2080ti Hall of Fame 10th anniversary limited edition  PSU: Asus ROG THOR 1200W  COOLER: Optimus foundation black acetal RADS: 3x EKWB CoolStream PE 360  LOOP: EKWB torque HDC fittings / EKWB ZMT 15,9/9,5mm / EKWB CryoFuel Clear MONITOR: Acer predator X34

Link to comment
Share on other sites

Link to post
Share on other sites

---

Join the Appleitionist cause! See spoiler below for answers to common questions that shouldn't be common!

Spoiler

Q: Do I have a virus?!
A: If you didn't click a sketchy email, haven't left your computer physically open to attack, haven't downloaded anything sketchy/free, know that your software hasn't been exploited in a new hack, then the answer is: probably not.

 

Q: What email/VPN should I use?
A: Proton mail and VPN are the best for email and VPNs respectively. (They're free in a good way)

 

Q: How can I stay anonymous on the (deep/dark) webzz???....

A: By learning how to de-anonymize everyone else; if you can do that, then you know what to do for yourself.

 

Q: What Linux distro is best for x y z?

A: Lubuntu for things with little processing power, Ubuntu for normal PCs, and if you need to do anything else then it's best if you do the research yourself.

 

Q: Why is my Linux giving me x y z error?

A: Have you not googled it? Are you sure StackOverflow doesn't have an answer? Does the error tell you what's wrong? If the answer is no to all of those, message me.

 

Link to comment
Share on other sites

Link to post
Share on other sites

7 hours ago, LtStaffel said:

I don't know what language Arduinos use, I hear it's something like C, therefore I don't know the language either. However, I see a function called "loop". How is that function looped? If you somehow have it set so that while the button is pressed it's retracted then that's your problem, you want it to sense the button press and trigger off of that and not the continuous button press.

My apologies if I'm not knowledgeable enough here, I'll delete this post if that's case. (or edit it to be tiny and less space wasting)

The language I used is C. The void setup is ran once and the main is hidden in arduino, what they give you is void loop which is an infinite loop once youve pasted the void setup

CPU: Intel Core i9-10900K  MOBO: ROG MAXIMUS XII FORMULA GPU: 2080ti Hall of Fame 10th anniversary limited edition  PSU: Asus ROG THOR 1200W  COOLER: Optimus foundation black acetal RADS: 3x EKWB CoolStream PE 360  LOOP: EKWB torque HDC fittings / EKWB ZMT 15,9/9,5mm / EKWB CryoFuel Clear MONITOR: Acer predator X34

Link to comment
Share on other sites

Link to post
Share on other sites

it's been a while since I've done anything with an arduino, but let's try this:

  • create a global variable on which you keep track of the state of the button (other than reading the value of the button)
  • create a global variable on which you keep track of the operation you have to perform (extend or retract)
  • at the beginning of the loop, store in a variable the current value of the button
  • if the current value is low
    • update the global variable with the current value
    • go to the next iteration of the loop
  • if the current value is high
    • if the value on the global button value variable is low
      • change the operation you have to do (change extend to retract or retract to extend)
    • update the global button value with the current value of the button
    • perform the operation the global operation variable tells you to do
    • go to the next iteration of the loop

this logic should make it work

The best way to measure the quality of a piece of code is "Oh F*** "s per line

Link to comment
Share on other sites

Link to post
Share on other sites

The following would be my approach.

 

#define POUS_OUT 4

enum MotionStatus {
    EXTENDING,
    RETRACTING
};

static currentMotionStatus{MotionStatus::RETRACTING}; //Tracks the status of the ladder
static bool oneShotLatchRelease{true}; //A latch to let the program know whether switching states is enabled
static int iNBtnR{0}; //Counter for Serial debug

inline bool buttonIsPressed() {
    return (digitalRead(BTN_R) == LOW); //If the BTN_R pin is low, the button is pressed
}

inline bool inManualMode() {
    return (digitalRead(SLT_VB) == HIGH); //If the SLT_VB pin is high, the machine is in manual mode
}

void poussoirManuel()//Function to extend the loader
{
    Serial.println(++iNBtnR); //Verification of statement entry for serial monitor debugging
    digitalWrite(POUS_OUT, HIGH);
    Serial.println("Pousse");
    currentMotionStatus = MotionStatus::EXTENDING; //Change the motion status
    oneShotLatchReleased = false; //You must set a flag that only releases once the button is released
}

void poussoirResetManuel()//Function to retract the loader
{
    Serial.println(++iNBtnR); //Verification of statement entry for serial monitor debugging
    digitalWrite(POUS_OUT, LOW);
    Serial.println("Reset");
    currentMotionStatus = MotionStatus::RETRACTING; //Change the motion status
    oneShotLatchReleased = false; //You must set a flag that only releases once the button is released
}

void setup() {
    pinMode(POUS_OUT, OUTPUT);
    poussoirResetManuel(); //Begin the sketch in a known, retracted state
    Serial.begin(9600);
}

void loop() {
    if (!buttonIsPressed()) {
        oneShotLatchReleased = true; //If the button is not pressed, it is okay to change states
    }
	if (inManualMode()) {
        if (currentMotionStatus == MotionStatus::RETRACTING) {
            if (buttonIsPressed() && oneShotLatchReleased) {
                poussoirManuel(); //Call the function that extends the loader              
            }
        } else {
            if (buttonIsPressed() && oneShotLatchReleased) {
                poussoirResetManuel(); //Call the function that retracts the loader
            }
        }
    }
}

 

Link to comment
Share on other sites

Link to post
Share on other sites

The contacts inside your button may be bouncing when you press the button down or remove the finger from your button.  So instead of having a straight forward 0 to 1 or 1 to 0, you may have a series of random 0s and 1s whenever the button is pressed or released.

 

If that's the case, you can solve this either in hardware or in your source code. For example, in hardware, you would add a resistor in series with the button, between the button and ground or between voltage and ground, depending on how you do your buttons in arduino. Something like 300-1000 ohm would do, whatever you have on hand.  Then, you add a capacitor between the button's pin and ground, something like 0.047 uF or 0.01 uF

 

For example, let's say you have it like this  [+5v ] ----- [ resistor ] ------ [ 1 button 2 ] --- [ + capacitor  ] --- i/o pin

When you press the button, the circuit closes and the resistor allows energy to go through and slowly charge up the capacitor, raising the voltage from 0v to 5v (slowly being microseconds). When the voltage on the capacitor goes above some threshold (see arduino chip documentation) which may be around 0.7v or  2v , then the arduino chip evaluates that as  digital 1.

So let's say the button contacts bounce inside when you press it, and you have for one microsecond 0100110 etc .. whenever there's a 1, a tiny bit of energy goes through and charges the capacitor a bit but not enough to reach that threshold voltage on the input pin to show up as digital 1.  When the button contacts are touching for enough time, the capacitor will be enough charged to go above that threshold and your microcontroller will see 1.

When you don't press the button anymore, the circuit is interrupted and the charged up capacitor will quickly discharge through the arduino i/o pin and go down near 0v so the io pin will report low / 0

 

Software debouncing is fairly simple ... basically you just read the button several times and "filter it". For example, you could use a char variable (0..255) and every time you read the button state , you add 1 or decrease 1 depending on the button state (pushed or not pushed), making sure to not go below 0 or 255.

When your variable is above some number, let's say 10 (meaning 10 out of maybe last 15-20 reads were 1) then you're fairly certain the button was pushed so your button state is 1. When the variable is 0, you know the button is not pushed.

This is a bit bad because every time you add or substract you have to do an if which adds cpu cycles to your code and increases the program code.

 

An approach that solves the if then else issues would be this. 

Use an unsigned 16 bit or 32 bit variable which basically means you can keep track of up to 16-32 button reads.

You read the button and if it's 1, you just shift the number to the left by 1 bit and add 1 (so the number of 1s to the right increases). If the button is 0, then you shift the number to the right by 1 bit (so you have more 0s to the left).

If there's 8 1s to the right, you're fairly certain the button is pressed. so basically if number >=255;  (or number & 255  == 255 or something like that). If it's 0, the state of your button is 0

 

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×