Self made shake switch

Dear Arduino-fans!

I am new to arduino and now I’ve set up a project.
I’ve made my own shake-switch, so if you shake the thing, it makes contact, in every direction. (he is working)
It is made with a piece of polystyrene, some nails, a small spring with some weight at the end and a screw.



Now I want to program it with my arduino.
I want to make a LED blink when it has made contact 5 times in 2 seconds.

So I was thinking:

int ledPin7 = 7;
int inPin4 = 4;
int val = 0;
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button
long firstPress = 0;
long countingTime = 3000;
int presses  = 0;

void setup() 
{
  pinMode(ledPin7,OUTPUT);
  pinMode(inPin2, INPUT); 
  }

void loop() 
{
     if(digitalRead(inPin4) == HIGH)
   {
	 firstPress = millis();
	 presses = 1;
	 while(millis() - firstPress < countingTime)
	 {
	     if(digitalRead(inPin4) == HIGH)
	     {
		   presses++;
}
}
if(digitalRead(inPin4) == HIGH)
 {
   firstPress = millis();
   presses = 5;
   digitalWrite(ledPin7,HIGH);	     
	 } 
} 
}

but this does not work! ;(
And I have no clue how to turn it off again when shaking(making contact) 5 times in 2 seconds again.

I think somewhere there has to be:

if(button_count == 21) button_count =0;

I’ve done a lot of research, but could not make it work!

Thanks,

Samory

First things first - it doesn't compile. Looks like a typo on the pinmode line that sets up the input. It also badly needs the attention of the IDE's autoformatter.

After that you'll need to look at debouncing your input - the tight while loop you have will likely register many many presses. The purpose of the code after the while loop eludes me.

int ledPin7 = 7;
int inPin4 = 4;
int val = 0;
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button
long firstPress = 0;
long countingTime = 3000;
int presses  = 0;

void setup() 
{
  pinMode(ledPin7,OUTPUT);
  pinMode(inPin4, INPUT); 
  }

void loop() 
{
     if(digitalRead(inPin4) == HIGH)
   {
	 firstPress = millis();
	 presses = 1;
	 while(millis() - firstPress < countingTime)
	 {
	     if(digitalRead(inPin4) == HIGH)
	     {
		   presses++;
}
}
if(digitalRead(inPin4) == HIGH)
 {
   firstPress = millis();
   presses = 5;
   digitalWrite(ledPin7,HIGH);	     
	 } 
} 
}

I don’t understand what i’ve typed after the ‘while’ because that part I used from another code I found. I tried to use the most useful things from diferent codes with some logical thinking and trial and error. Since I’ve never programmed, this is realy hard! I jumped into arduino with some small blinking exercises (delay) and some button press exercises.

so, you’re suggestion is to remove the ‘millis() - firstPress < countingTime’ or replace it by?

And you're saying I'll have a lot of hits, so you mean I have to raise the amount of presses? Or do I have to use 'presses >= 5'?

If you’re really interested in the number of presses you got, you’ll need to consider transitions from low to high so that two checks in rapid succession don’t count two when nothing has changed. You will also get additional presses even then because of contact bounce, as with any switch - search the forums for debounce for more data, but delay(10) if often enough after you detect a transition.

On the other hand, if you just care that the device has been shaken for two seconds then you can find out by experiment how many presses that is and if it’s consistent enough for you to use.

That would be good enough!

I know what to do, but I can't translate it in Code language

const int  buttonPin = 4; 
const int ledPin = 7; 
int buttonPushCounter = 0;   
int buttonState = 0; 
int lastButtonState = 0;   

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  buttonState = digitalRead(buttonPin);
  if (buttonState != lastButtonState) {
         buttonPushCounter++;
    } 
 if (buttonPushCounter = 10) {
    digitalWrite(ledPin, HIGH);
  } else {
   digitalWrite(ledPin, LOW);
  }
  } 
}

But this does not work! ;(

  if (buttonState != lastButtonState) {

You never assign lastButtonState the current switch state.

 if (buttonPushCounter = 10) {

Assigning buttonPushCounter the value of 10 is always true.

As you'll see in responses in many many threads - "But this does not work" is really not very helpful. What does it do? What did you expect? I'm guessing the led is always on whether you've shaken it or not, but it is hard to offer advice without a little data.

Indeed, as you say, the LED is always on!
Even if i close the switch, nothing changes!

I was expecting that the LED would be turned off when i uploaded (or gave the arduino power) the code, and when i closed the switch 10 times, the led would turn on.

When the LED is on (after 10 touches) I want the arduino stop counting with a delay of 10000 (10 seconds) and reset.
So then I can write the code for the turn off in the same way as the turn on.

@PaulS
Do you mean it has to be something like previousButtonState, or?

How can I make the LED react after 10 touches?

sorry that I really don’t know a lot about this! :frowning:

You should learn, now, to use Serial.begin() in setup() and Serial.print() and Serial.println() in setup() and loop() to debug your own code.

The suggestion that you need to compare the current state of the switch to the previous state is what led you to add:

 if (buttonState != lastButtonState) {

to your code. This works fine for the first pass through loop(), when there is no previous state to compare to. At the end of loop(), you need to save the current state somewhere, so that on the next pass, there is a previous state to compare to. I'm thinking that lastButtonState is probably a good place to do that.

How can I make the LED react after 10 touches?

First, you have to properly count 10 touches.

Your most immediate problem, as PaulS mentioned, is this line:

if (buttonPushCounter = 10) {

You are assigning the value ten to buttonPushCounter and then using an if statement to check if it is non-zero. It is one of the classic errors in C - you meant to use ==

As written it probably still won't work because of the debounce issue I keep harping on about. You might at least get the led off and then on forever after some shaking if you used >= 10 instead.

First I want to thanks you for all your quick responses!

I'm looking on the web for multiple days for a possible solution, also tried at least 100 codes, but I didn't succeed! It is for my final assignment at the university, the arduino aspect is not the most important, but it has to work for my product! I know I sound desperate, I sound like that because I am! I only have few weeks left for a lot of other stuf i have to do (making plastic prototypes and stuff, technical files, ..) I am a industrial productdesign student btw!

After the assignment, I am going to learn a lot about arduino, because I love it, and it may be usefull in further prototypes in real business life! :p

When I change the = in ==, the LED start blinking, very short..

the 'Serial.begin()' and stuf, isn't this for sending information to your computer? I don't think this is necessary..

Just:

if 10 times buttonPin = HIGH; then(ledPin7 = HIGH); if(buttonPushCounter == 20) buttonPushCounter =0;

if 10 times buttonPin = HIGH; then(ledPin7 = LOW);

the ‘Serial.begin()’ and stuf, isn’t this for sending information to your computer?

Yes it is. That “stuff” can include debug information. Like, the switch state is the same as/is different from last time. The count is…

I don’t think this is necessary…

You are entitled to your opinion. No matter how wrong I think it is. :slight_smile:

You are thinking that each time the spring contacts the surrounding metal, there will be one count. That is not true. When the switch contacts the surrounding metal, the state will be HIGH. When there is no contact, the state will be LOW. What you need to count is when the state IS high but was low. If the state is high and was high, ignore it. If the state is low and was low, ignore it. If the state is low and was high, ignore it.

Only increment the counter when the state IS high and WAS low.

Oke, oke, I believe you! :p Well, this information was very useful!

But, if the 'Serial.begin()', ... communicate with the computer while using it, is it possible to use my arduino with the program without computer, and just a battery?

is it possible to use my arduino with the program without computer, and just a battery?

Yes. In the context of your sketch, you only need the serial commands to help you debug. You can remove them later if you like, or leave them in - you're not bound to have the arduino attached to a PC just because you're using the serial port. Anything sent there when detached just doesn't get read by anything.

Now I have something like a basic code, but It still isn’t working! ;(

int value = 0;
 
const int in4Pin = 4;
const int led8Pin = 8;
const int led7Pin = 7;
int buttonPushCounter = 0;   
int buttonState = 0;         
int lastButtonState = 0;    
  
 
void setup()
{
  pinMode(in4Pin, INPUT);
  pinMode(led7Pin, OUTPUT);
  pinMode(led8Pin, OUTPUT);
 
   Serial.begin(9600);
 
}
  
 
void loop() {
 
   buttonState = digitalRead(in4Pin);
  
   if (buttonState != lastButtonState) {
      if (buttonState == HIGH) {
        buttonPushCounter++;
       Serial.println("on");
       Serial.print("number of button pushes:  ");
       Serial.println(buttonPushCounter, DEC);
     } 
    else {
        Serial.println("off"); 
    }
   }
    lastButtonState = buttonState;
 if (buttonPushCounter == 10 ) 
{
   digitalWrite(led7Pin, HIGH);
   digitalWrite(led8Pin, HIGH);
  } else {
   digitalWrite(led7Pin, LOW);
    digitalWrite(led8Pin, LOW);
}
}