Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 22:17 29 Mar 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Maximite 2: How to make switch trigger only once when pressed

Author Message
Decoy
Senior Member

Joined: 02/08/2019
Location: Denmark
Posts: 109
Posted: 11:30am 30 Nov 2020
Copy link to clipboard 
Print this post

Hi guys

I finally had some time with the Maximite 2, after building a couple of them several months ago. I am recovering from my double-incision distal bicep tendon repair, so everything is done with the left hand

I've managed to hook up a switch, with a cap to prevence bouncing (Arduino-style). How would I go about making the switch only register once per press, to avoid holding in the switch being seen as constant presses. I think I used the millis() function in Arduino ages ago - buw to do this on Maximite 2? Maybe a pre-made function exists?

Something like:

variable = 0
if button is pressed then variable = variable +1

I need the variable to count only once per press, then the switch must be depressed before pressing (and adding to variable) again.

Any advice?
Thanks!
 
jirsoft

Guru

Joined: 18/09/2020
Location: Czech Republic
Posts: 532
Posted: 11:38am 30 Nov 2020
Copy link to clipboard 
Print this post

What about something like:

'initialisation
DIM INTEGER prev = -1


and in function for key:
IF button <> prev THEN
      prev = button
      IF button THEN
             'BUTTON PRESSED!
      ELSE
             'BUTTON DEPRESSED!
      ENDIF
ENDIF

Jiri
Napoleon Commander and SimplEd for CMM2 (GitHub),  CMM2.fun
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 3422
Posted: 12:30pm 30 Nov 2020
Copy link to clipboard 
Print this post

There is a writeup about this

http://fruitoftheshed.com/MMBasic.Switch-de-bounce-uses-Ganssels-Algorithm-for-Zero-Delays.ashx
PicomiteVGA PETSCII ROBOTS
 
Decoy
Senior Member

Joined: 02/08/2019
Location: Denmark
Posts: 109
Posted: 04:37pm 30 Nov 2020
Copy link to clipboard 
Print this post

Thanks guys

A part of me is a little bit   about this. I used to do it with millis() on arduino ages ago, but the last many years I have become used to GML (Gamemaker Studio 2-code) which just has a function for this. It seems like something almost everybody will need to use, whether they only do software or also hardware.

If anybody has suggestions for the sleakest way to implement this, I would love to know.
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5867
Posted: 08:01pm 30 Nov 2020
Copy link to clipboard 
Print this post

Does not qualify for "sleakest way" but it might be a start for you
Use any digital pin and switch pulls input to ground. Internal pullup should be adequate but you could use external resistor to 3.3V instead.

A capacitor is always advisable although the debounce timer should stop bounce triggers. The capacitor will reduce the number of calls to the sub.

It assumes that you don't reset the timer anywhere in your program.

 OPTION EXPLICIT
 OPTION DEFAULT NONE
 CONST sw_pin = 10
 const debounce = 200
 DIM INTEGER sw_action
 
 SETPIN sw_pin, INTB, clicked, PULLUP
 
 DO
   IF sw_action = 1 THEN
     PRINT "clicked"
     sw_action = 0 ' reset the flag
   ENDIF
   
 LOOP
 
SUB clicked
 STATIC INTEGER old_sw_state, old_time
 LOCAL INTEGER sw_state, new_time, interval
 sw_state = PIN(sw_pin)
 new_time = TIMER
 interval = new_time - old_time
 print "*" ' debug info to show contact bounces
 IF sw_state <> old_sw_state AND interval > debounce THEN
   old_sw_state = sw_state
   old_time = new_time
   IF sw_state = 0 THEN sw_action = 1 ' only set the flag with switch low
 ENDIF
END SUB


(I am one of the lucky ones, it's my left hand that's no use)

Jim
VK7JH
MMedit   MMBasic Help
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3641
Posted: 10:03pm 30 Nov 2020
Copy link to clipboard 
Print this post

  Decoy said  I have become used to GML (Gamemaker Studio 2-code) which just has a function for this.

What's it called please / how does it do it?

John
 
Decoy
Senior Member

Joined: 02/08/2019
Location: Denmark
Posts: 109
Posted: 05:10pm 01 Dec 2020
Copy link to clipboard 
Print this post

  JohnS said  
  Decoy said  I have become used to GML (Gamemaker Studio 2-code) which just has a function for this.

What's it called please / how does it do it?

John


John, the normal function in GML is:

Keyboard_check(key)

- This will count as a press for each cycle that the key is pressed

The other function is:

keyboard_check_pressed(key)

- this will only register once, then the key will need to be depressed before pressing it again. I have no idea what goes on behind the scenes :)

The above also work for inputs from a microcontroller through a .dll.

I sort of expected a high-level language such as BASIC to have an easier implementation of this than C++ or the like. Jim's example above is great, but it is as - if not more - involved, than the Arduino counterpart.

.
Edited 2020-12-02 03:12 by Decoy
 
Turbo46

Guru

Joined: 24/12/2017
Location: Australia
Posts: 1584
Posted: 07:16pm 01 Dec 2020
Copy link to clipboard 
Print this post

In Geoff's Programming with the Colour Maximite 2 Document there is a chapter on Using a Switch as an Input on page 62.

I would use an external pullup resistor because I have found that when using the internal pullup resistor, sometimes noise can trigger false inputs if the wire to the switch is too long. 100mS delay to allow for switch bounce has worked well for me.

I would use an interrupt on low for the switch input pin so that, depending on what your program is doing, it wont miss a short button push.

The interrupt subroutine would:
 disable interrupts to stop contact bounce re-triggering it.
 set a flag to show the switch has operated
and return

In the main program loop (having cleared the flag and set up the pin first)
.
.
check the flag
if it is set then
 pause 100mS (to de-bounce the switch)
 increment the variable
 clear the flag
 re-enable the interrupt on low
endif
.
.
loop

That could be best done in a subroutine.

I hope you're on the mend. I know from experience that paper work can be difficult left-handed.
Bill
Keep safe. Live long and prosper.
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3641
Posted: 07:37pm 01 Dec 2020
Copy link to clipboard 
Print this post

I can imagine just wrapping the MMBasic features up to provide those.  Whether someone wants to bother and whether it's good to hide reality away I don't know.

John
 
Turbo46

Guru

Joined: 24/12/2017
Location: Australia
Posts: 1584
Posted: 08:33pm 01 Dec 2020
Copy link to clipboard 
Print this post

I don't like to hide things away. If I can read the code maybe I can understand it and learn from it. I didn't give code because I am not sure of Decoy's knowledge and it may help him learn by finding the instructions and how to use them.

You could always check out Fruit-of-the-shed for examples. See this one for example.

Bill
Keep safe. Live long and prosper.
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5867
Posted: 08:54pm 01 Dec 2020
Copy link to clipboard 
Print this post

Keyboard_check(key)
and
keyboard_check_pressed(key)

sound like KEYDOWN and INKEY$,
but I thought we were talking about switches, not the keyboard.

My example and the others referred to hide the complexity from you if you don't want to know but allow you to fine tune them to suit special uses.
That is the advantage of doing it in user functions instead of a built-in command.

Jim
VK7JH
MMedit   MMBasic Help
 
Decoy
Senior Member

Joined: 02/08/2019
Location: Denmark
Posts: 109
Posted: 04:33pm 02 Dec 2020
Copy link to clipboard 
Print this post

Jim, what is the issue with your arm? If I may ask.

I am getting the cast off in 10 days, then 10 years of rehabilitation  

Regarding my programming skills: I never recieved any training or courses in programming. I took my master's degree in biotechnology. I work in microbiology. Some years ago I decided to learn about programming - mostly due to video games.

Several years ago I made the "first Danish arcade game" which was later sold to an arcade in Copenhagen. After that I made a program that calculate bacterial counts from plated dilution ranges along with count uncertainty presented in CFU and %. I recently released a game on Steam as well, and I am working on another game right now - and also a physical microcontroller-based bacterial count calculator for use directly in the lab to avoid having to write down/bring results out of the lab for later calucation. This is where I used millis() to do the button presses.

My point is, I have many hobbies - and sub-hobbies. I am not afraid of the difficult stuff - I just try to find the easiest path with some projects. It would not be fair to compare my programming skills to people that are professional programmers. Unless it also goes the other way, such as "how would you make a bacteria competent and how would you introduce new DNA into the bacterial cell? By transduction, transformation or conjugation?".

So, it probably was a wrong assumption to make - that BASIC had a more direct way of doing it, that would be shorter and easier than a low-level language. But I will do it the correct way  

Thanks guys - I love this forum and its users! Especially when they push me. Tomorrow I'll probably take it all back when I realize I was wrong.


.
Edited 2020-12-03 02:33 by Decoy
 
Tinine
Guru

Joined: 30/03/2016
Location: United Kingdom
Posts: 1646
Posted: 05:37pm 02 Dec 2020
Copy link to clipboard 
Print this post

If I understand the requirements, I would do something like:



Do

If [button input] Then

 Select Case DbChk
   Case 0
     DbTmr = Timer + 100
     DbChk = 1
   Case 1
     If Timer > DbTmr Then
       var = var +1
       DbChk =2
     End if
   Case 2 'let go of the button dammit
 End Select

Else
 DbChk = 0
End if

Loop

 
Decoy
Senior Member

Joined: 02/08/2019
Location: Denmark
Posts: 109
Posted: 08:57pm 02 Dec 2020
Copy link to clipboard 
Print this post

  Tinine said  If I understand the requirements, I would do something like:



Do

If [button input] Then

 Select Case DbChk
   Case 0
     DbTmr = Timer + 100
     DbChk = 1
   Case 1
     If Timer > DbTmr Then
       var = var +1
       DbChk =2
     End if
   Case 2 'let go of the button dammit
 End Select

Else
 DbChk = 0
End if

Loop


I really like this switch statement approach! Thanks!


.
 
Tinine
Guru

Joined: 30/03/2016
Location: United Kingdom
Posts: 1646
Posted: 01:32am 03 Dec 2020
Copy link to clipboard 
Print this post

Still too many lines of code for my liking but I have never used the PULSIN function...Would that be an option?

Edit: Hmmm, I guess that the PULSIN would hold up execution (?) which is a no-no for me.
Edited 2020-12-03 11:53 by Tinine
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5867
Posted: 02:24am 03 Dec 2020
Copy link to clipboard 
Print this post

  Decoy said  Jim, what is the issue with your arm? If I may ask.

Neurological so not fixable.

The code used will depend on the requirements.

In my joystick code, the buttons are scanned every 16mS and only interested in the current state so no de-bounce required.

My water flow monitoring wouldn't like too many bounces so it needs de-bounce. I used capacitors rather than code so the MMBasic 'count' option can be used.

Do you want fast response? That leaves you open to short spikes being seen but could limit the rate they are seen at.

If you don't mind a slower response, de-bounce code will eliminate the stray spikes.

How much delay will depend on your choices.

If I want to use my fingers and cheap switches, I would need a ridiculously long de-bounce time.

You might want to multipurpose the switch. Short press for one action, long press for something different.

Or maybe, a repeat function.

Lots of choices and MMBasic can do them all.

Jim
VK7JH
MMedit   MMBasic Help
 
Decoy
Senior Member

Joined: 02/08/2019
Location: Denmark
Posts: 109
Posted: 05:40am 03 Dec 2020
Copy link to clipboard 
Print this post

  Tinine said  Still too many lines of code for my liking but I have never used the PULSIN function...Would that be an option?

Edit: Hmmm, I guess that the PULSIN would hold up execution (?) which is a no-no for me.


Well, one thing - I prefer debouncing in hardware rather than code. Or that is how I usually do it. I also do not need a very fast read. It should fit with a finger pressing a button.

As Jim states above, maybe a solution would need to include a different outcome when the switch is held.

.
 
Tinine
Guru

Joined: 30/03/2016
Location: United Kingdom
Posts: 1646
Posted: 06:37am 03 Dec 2020
Copy link to clipboard 
Print this post

Not a problem with my Select Case example; any contact bounce would cause a reset of the timer and the contacts would need to remain closed for 100ms to register as a valid signal. The Case 2 is do-nothing while the input is still high and that can be used for a long press if required.
 
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024