Debounce code for push-buttons in project

Go To Last Post
103 posts / 0 new

Pages

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

By having the inputs floating, the results will be indeterminate. Either put a 10k resistor to 5V on each of the inputs or enable the internal pullups. To activate the ‘switch’, connect the required port pin to 0V.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You don't get it yet.  able to make the test to the 2 pins with only 1x 10k ohm resistor, instead of having 2x 10k ohm resistor, 1 for each pin.

 

Why do you keep talking about & showing only one resistor?  Does your setup match the correct drawing given by Clawson?

 

There must be TWO resistors, one going from 5v to PD2, and another resistor going from 5V to PD3.  It really can't be any simpler (other than using the built-in pullups)...It is better to add your own for now, since you are sure they are taking effect.  The built-ins, require your software to be correct in order to activate those.

 

You can use wires to gnd to pull either or both pins to gnd as desired (or get some switches).  Why are you messing with debouncing switches, when you don't have any (just wondering)? 

When in the dark remember-the future looks brighter than ever.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman already understood what I was trying to say. And I already understood you you all are saying. And I'll make the changes to match what I need to have.

avrcandies, I was talking and showing what I had in hardware because it was what I had in hardware in fact. Ok, its not correct, but it was what I had, ok? Got it? My mistake might only be to have one of the 2 pins floating when I shouldn't and I'll fix that later today, but that was what I had on the breadboard.
And I've already ordered a complete set of several different push-button from eBay, but they will take quite a while to arrive, so as we use to say around "if you don't have a dog, you'll have to hunt with a cat..."

Later today, after work ill be back to my tests.
Thanks

Last Edited: Tue. Jul 10, 2018 - 06:15 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That's good that your are fixing up your setup...having real switches will make checking things out a lot better.  Things may start off rocky, but you'll get there step-by-step.   Keep experimenting and live the dream! 

When in the dark remember-the future looks brighter than ever.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There are four possible causes for your problems...

 

1) Hardware Design - what your hardware should look like

2) Hardware Implementation - what you actually built, including any faults

3) Software Design - the algorithm used

4) Software Implementation - What the compiler outputs

 

It sounds like 1) is sorted when you follow the advice given above. We know 3) is OK because I've used your exact code and it works on my board here. So that leaves 2) or 4).

 

With regards to 4) there has been some discussion about the use of 'volatile'. I have proved that on one version of the compiler it doesn't matter. On other versions it might (although there is a different argument about whether that behavior is correct).

 

To help eliminate 4), and hence prove your problem lies with 2) could you...

 

a) compile the non-working code as you posted back in post #19

b) find the .LSS file generated

c) copy and paste the whole .LSS file into this topic

 

Thanks.

 

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello.

Sorry for the late reply.

Today was a rough day. My only spare time was last 10 minutes I took to add an extra 10k ohm resistor to PD3 (PD2 already had one) and try to load the code again and test. LED is always ON even so!

 

I couldn't do any more testing and I'm about to go to bed. Just time to tell the files I have after compilation:

debounce.srec

debounce.o

debounce.map

debounce.lst

debounce.hex

debounce.elf

debounce.c

debounce.bin

debounce_eeprom.srec

debounce_eeprom.hex

debounce_eeprom.bin

 

no .LSS file.

 

Let me know what else you need. I had no time to perform all the other fail safe checks that Brain told me! Tomorrow I'll try to re-check wirings and hardware and paste here compilation output if needed, and also my Makefile!

 

Thanks

Psy

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Hello, 

   I suggest that instead of learning to understand the Mega328P AVR microcontroller as a device, learn instead how to interface simple and cheap module boards to the Mega328P that is the key component of the Arduino system.  I suggest thinking of the Arduino UNO or Nano as the lowest level of hardware that you should spend time learning.  Instead, learn I2C {TWI in Atmel language, Wire.h in Arduino language} by connecting a cheap DS3231 clock module to the AVR (on the standardized single-board hardware development platform, the Arduino).  Get an LCD 16x2 char display or a ST7735 TFT 160x128 SPI display and add it to the system.  Download the libraries for Arduino in GitHub for these parts.  Study the code.  This is the place where everybody tries to show that Arduino is not a toy by using every academic trick that they learned in C++ programming school in the library application that they are offering.  So you will get a crash, "sink or swim" course in C++ coding.  Most of the time, when you have the hardware connected correctly, and the example code will compile correctly, then your application /.ino /sketch/program/ will run its demo correctly.  Even if you are not exactly sure what is happening, or what the data that you are receiving means.

 

  Other cheap interesting interface-module boards on eBay are the RDA5807M FM-radio receiver,  the INA219 I2C voltage/amp meter, the AD9833 Sine/Triangle/Square programmable function generator,  the DFPlayer MP3 module that reads music directly from SD chip/cards, the VS1053 MP3 player/Ogg recorder/MIDI tone module audio-processor board, the compass-gyro-accelemeter MEMS ICs. 

 

  It's better to learn CPU to peripheral interfacing and user-interaction systems than it is to learn the internals of an individual processor.

  My two cents worth.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

debounce.lst will do just fine thankyou.

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brian Fairchild wrote:
debounce.lst will do just fine thankyou.
Err no - it's unlinked. It's the LSS that is created by an "objdump -S" from the ELF that is more useful. As7 has a tick box somewhere in the project setting to say "and create an LSS". I though this was enabled by default but I guess OP must have disabled it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

Err no - it's unlinked. It's the LSS that is created by an "objdump -S" from the ELF that is more useful. As7 has a tick box somewhere in the project setting to say "and create an LSS". I though this was enabled by default but I guess OP must have disabled it.

 

Thanks. So, @OP, it's the .LSS we want.

 

(boy, you GCC types have it tough, so many hoops to jump through and options to set. wink)

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brian Fairchild wrote:
(boy, you GCC types have it tough, so many hoops to jump through and options to set.
And yet that is why most of us love GCC as it has literally hundreds of options which mean you can get it to do pretty much anything you ever hoped to achieve with a compiler. In fact GC+binutils have grown organically with 10,000's of programmers, each with their own requirements, saying "if only the compiler/linker could do this too" so each one adds the feature they are looking for and as long as it's considered an attractive feature to have and is implemented without obvious bugs the core team permit these things to be added making GCC perhaps the most configurable compiler/linker toolchain you can use. This is the joy of FOSS software!

 

Of course the downside is that there are myriad options and a beginner does not know which are the vital "must have" things and which are some esoteric mind trip only of use to some Icelandic code hacker on every third Thursday in July. Take optimisation for instance. Some compilers just have "on / off" or "on / mild / aggressive" and while GCC does have "grouping" options such as -O0, -O1, -O2, -O3, -Os, -Og these are just picking 10 or 20 or 30 options to be applied all at once. But every last optimisation option is individually switchable:

 

https://gcc.gnu.org/onlinedocs/g...

 

That page documents just the options to control optimization in GCC and that page is 1,900 lines long!! It can take a lifetime's work to study and understand every last option that GCC offers (I learn something new at least once a week if not once a day!) so yeah, I guess that could be considered "jumping through hoops". But personally I wouldn't have it any other way.

 

(I first started to use GCC for ARM projects in the early 90's - almost 30 years later and I'm still learning!)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello.

 

Which then is the option to enable the creation of these .LSS files? I have -Os enabled in my Makefile.

 

 

Edited;

 

I have this in my Makefile:

 

%.lst: %.elf
	$(OBJDUMP) -h -S $< > $@

 

So, maybe the .LSS file you're looking for is probably with the same content as my actual .lst, no?

Last Edited: Thu. Jul 12, 2018 - 08:20 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, beyond the fact that I was using active-low (resistor from pin to +5VDC and wire to short to GND when I wanted something to happen), I already reversed this situation and connected PD2 and PD3 to GND through 2 10k ohm resistors and used a wire to touch +5VDC to make the LED to switch state, but still not happening.

 

Here is .LSS file content:

 


debounce.elf:     file format elf32-avr

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .data         00000000  00800100  00000130  000001c4  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  1 .text         00000130  00000000  00000000  00000094  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .bss          00000004  00800100  00800100  000001c4  2**0
                  ALLOC
  3 .stab         000006c0  00000000  00000000  000001c4  2**2
                  CONTENTS, READONLY, DEBUGGING
  4 .stabstr      00000cc3  00000000  00000000  00000884  2**0
                  CONTENTS, READONLY, DEBUGGING
  5 .comment      00000011  00000000  00000000  00001547  2**0
                  CONTENTS, READONLY
  6 .note.gnu.avr.deviceinfo 00000040  00000000  00000000  00001558  2**2
                  CONTENTS, READONLY

Disassembly of section .text:

00000000 <__vectors>:
   0:	0c 94 34 00 	jmp	0x68	; 0x68 <__ctors_end>
   4:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
   8:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
   c:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  10:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  14:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  18:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  1c:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  20:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  24:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  28:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  2c:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  30:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  34:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  38:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  3c:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  40:	0c 94 59 00 	jmp	0xb2	; 0xb2 <__vector_16>
  44:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  48:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  4c:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  50:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  54:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  58:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  5c:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  60:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  64:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>

00000068 <__ctors_end>:
  68:	11 24       	eor	r1, r1
  6a:	1f be       	out	0x3f, r1	; 63
  6c:	cf ef       	ldi	r28, 0xFF	; 255
  6e:	d8 e0       	ldi	r29, 0x08	; 8
  70:	de bf       	out	0x3e, r29	; 62
  72:	cd bf       	out	0x3d, r28	; 61

00000074 <__do_clear_bss>:
  74:	21 e0       	ldi	r18, 0x01	; 1
  76:	a0 e0       	ldi	r26, 0x00	; 0
  78:	b1 e0       	ldi	r27, 0x01	; 1
  7a:	01 c0       	rjmp	.+2      	; 0x7e <.do_clear_bss_start>

0000007c <.do_clear_bss_loop>:
  7c:	1d 92       	st	X+, r1

0000007e <.do_clear_bss_start>:
  7e:	a4 30       	cpi	r26, 0x04	; 4
  80:	b2 07       	cpc	r27, r18
  82:	e1 f7       	brne	.-8      	; 0x7c <.do_clear_bss_loop>
  84:	0e 94 89 00 	call	0x112	; 0x112 <main>
  88:	0c 94 96 00 	jmp	0x12c	; 0x12c <_exit>

0000008c <__bad_interrupt>:
  8c:	0c 94 00 00 	jmp	0	; 0x0 <__vectors>

00000090 <get_key_press>:

volatile uint8_t key_state = 0;
volatile uint8_t key_press = 0;

uint8_t get_key_press(uint8_t key_mask){
   cli();
  90:	f8 94       	cli
   key_mask &= key_press;              //read key(s)
  92:	90 91 00 01 	lds	r25, 0x0100	; 0x800100 <_edata>
  96:	89 23       	and	r24, r25
   key_press ^= key_mask;              //clear key(s)
  98:	90 91 00 01 	lds	r25, 0x0100	; 0x800100 <_edata>
  9c:	98 27       	eor	r25, r24
  9e:	90 93 00 01 	sts	0x0100, r25	; 0x800100 <_edata>
   sei();
  a2:	78 94       	sei

   return key_mask;
}
  a4:	08 95       	ret

000000a6 <timer_intr_setup>:

void timer_intr_setup(void){
   TCCR0B = 1 << CS02;                 //divide 256 * 256
  a6:	84 e0       	ldi	r24, 0x04	; 4
  a8:	85 bd       	out	0x25, r24	; 37
   TIMSK0 = 1 << TOIE0;                //enable timer interrupt
  aa:	81 e0       	ldi	r24, 0x01	; 1
  ac:	80 93 6e 00 	sts	0x006E, r24	; 0x80006e <__TEXT_REGION_LENGTH__+0x7e006e>
  b0:	08 95       	ret

000000b2 <__vector_16>:
  b2:	1f 92       	push	r1
  b4:	0f 92       	push	r0
  b6:	0f b6       	in	r0, 0x3f	; 63
  b8:	0f 92       	push	r0
  ba:	11 24       	eor	r1, r1
  bc:	2f 93       	push	r18
  be:	8f 93       	push	r24
  c0:	9f 93       	push	r25
  c2:	90 91 01 01 	lds	r25, 0x0101	; 0x800101 <key_state>
  c6:	29 b1       	in	r18, 0x09	; 9
  c8:	20 95       	com	r18
  ca:	29 27       	eor	r18, r25
  cc:	80 91 03 01 	lds	r24, 0x0103	; 0x800103 <ct0.1657>
  d0:	82 23       	and	r24, r18
  d2:	80 95       	com	r24
  d4:	80 93 03 01 	sts	0x0103, r24	; 0x800103 <ct0.1657>
  d8:	90 91 02 01 	lds	r25, 0x0102	; 0x800102 <ct1.1658>
  dc:	92 23       	and	r25, r18
  de:	98 27       	eor	r25, r24
  e0:	90 93 02 01 	sts	0x0102, r25	; 0x800102 <ct1.1658>
  e4:	82 23       	and	r24, r18
  e6:	89 23       	and	r24, r25
  e8:	90 91 01 01 	lds	r25, 0x0101	; 0x800101 <key_state>
  ec:	98 27       	eor	r25, r24
  ee:	90 93 01 01 	sts	0x0101, r25	; 0x800101 <key_state>
  f2:	20 91 01 01 	lds	r18, 0x0101	; 0x800101 <key_state>
  f6:	90 91 00 01 	lds	r25, 0x0100	; 0x800100 <_edata>
  fa:	82 23       	and	r24, r18
  fc:	89 2b       	or	r24, r25
  fe:	80 93 00 01 	sts	0x0100, r24	; 0x800100 <_edata>
 102:	9f 91       	pop	r25
 104:	8f 91       	pop	r24
 106:	2f 91       	pop	r18
 108:	0f 90       	pop	r0
 10a:	0f be       	out	0x3f, r0	; 63
 10c:	0f 90       	pop	r0
 10e:	1f 90       	pop	r1
 110:	18 95       	reti

00000112 <main>:
}


int main(void){

   timer_intr_setup();
 112:	0e 94 53 00 	call	0xa6	; 0xa6 <timer_intr_setup>

   LED_DIR = 0xff;
 116:	8f ef       	ldi	r24, 0xFF	; 255
 118:	84 b9       	out	0x04, r24	; 4
   LED_OUTPUT = 0xff;
 11a:	85 b9       	out	0x05, r24	; 5
   sei();
 11c:	78 94       	sei
   for(;;){
      LED_OUTPUT ^= get_key_press(0x0c);
 11e:	8c e0       	ldi	r24, 0x0C	; 12
 120:	0e 94 48 00 	call	0x90	; 0x90 <get_key_press>
 124:	95 b1       	in	r25, 0x05	; 5
 126:	89 27       	eor	r24, r25
 128:	85 b9       	out	0x05, r24	; 5
   }
 12a:	f9 cf       	rjmp	.-14     	; 0x11e <main+0xc>

0000012c <_exit>:
 12c:	f8 94       	cli

0000012e <__stop_program>:
 12e:	ff cf       	rjmp	.-2      	; 0x12e <__stop_program>

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok so what do you expect to happen? What actually happens?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, as I remember that someone said here these 2 pins, PD2 and PD3, should be active-high for this code, I connected both 10k ohm resistors, each one from each pin to GND and I'm using a wire to short either of these 2 pins to +5VDC and I was expecting to see LED going ON/OFF but LED is always ON.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What do you mean LED?  Shouldn't you have two of them?  How would two switches control an LED (maybe if either is pressed, then light the led).

 

Debouncing is pretty straightforward, not sure why you're messing around so much.

 

Make it easy:

set up a timer irq that fires 200 times a sec

in the irq check switch A, if it is pressed:

   increment countA, limit the count to 40 max

else decrement countA, don't let it go below zero

 

Do the same thing for switch B (countB)

 

===============

in your main code  if countA is > 20 then the switch is pressed & do what you want

likewise for B

 

You can write this in 15 minutes and be done.  That's as dirt-quick as it gets & works GRRRRRRREAT.

 

When in the dark remember-the future looks brighter than ever.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, but I'll be reading a bit about the timer thing in the datasheet, so I might take longer. I don't know how to set the time I want the overflow to occur (1/200 of a sec), so I need to read to see if I can figure it out!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here fellow freak; this gives you everything you need for the timer0 setup

 

http://maxembedded.com/2011/07/avr-timers-ctc-mode/

 

 

When in the dark remember-the future looks brighter than ever.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:

Here fellow freak; this gives you everything you need for the timer0 setup

 

http://maxembedded.com/2011/07/avr-timers-ctc-mode/

 

 

 

That was one of the resources I was reading, thank you! :)

Last Edited: Sat. Jul 14, 2018 - 07:16 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:

Here is .LSS file content:...

 

Well, unless I've missed something, the lack of 'volatile' is not the cause of your problems here.

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:

Debouncing is pretty straightforward, not sure why you're messing around so much.

 

It is, and the code the OP posted back in #19 works.

 

And it works for either active-high or active-low inputs. (Think about it, we debounce both rising and falling edges of a switch closing/opening. The software does not care what the inactive state of the switch is. It's only when we come to interpret the result that it matters).

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@OP  can you post the .hex file and I'll run it on known working hardware.

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So, to clear things out:

 

Does it matters if I'm using active-low or active high in PD2 and PD3 or not?

 

Either ways, .hex file content is this:

 

:100000000C9434000C9446000C9446000C9446006A
:100010000C9446000C9446000C9446000C94460048
:100020000C9446000C9446000C9446000C94460038
:100030000C9446000C9446000C9446000C94460028
:100040000C9457000C9446000C9446000C94460007
:100050000C9446000C9446000C9446000C94460008
:100060000C9446000C94460011241FBECFEFD8E03C
:10007000DEBFCDBF21E0A0E0B1E001C01D92A43001
:10008000B207E1F70E9487000C9494000C940000E2
:10009000F894909100018923982790930001789417
:1000A000089584E085BD81E080936E0008951F92DD
:1000B0000F920FB60F9211242F933F938F939F931C
:1000C0003091010129B120952327809103018223DA
:1000D0008095809303019091020192239827909339
:1000E00002012823822F8923982F932790930101BF
:1000F000892390910001892B809300019F918F911A
:100100003F912F910F900FBE0F901F9018950E9456
:1001100051008FEF84B985B978948CE00E94480033
:0C01200095B1892785B9F9CFF894FFCF7D
:00000001FF

 

And I was now testing a code made by myself, trying to follow post #67 suggestions from avrcandies.

 

//Datasheet used
//http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega328_P%20AVR%20MCU%20with%20picoPower%20Technology%20Data%20Sheet%2040001984A.pdf

#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>

#define COUNT 20

volatile uint8_t counter = 0;

int main(void){

   DDRB = 0xff;


   //Using Timer1, page 152
   //Prescaler to be used, if needed, Table 20-7, page 177
   TCCR1B = (1 << CS11); //prescaler of 8

   //Operation mode, Table 20-6, pages 175 and 176
   TCCR1A = (1 << WGM11) | (1 << WGM10); //set mode to Fast PWM, triggering interrupt at TOP value of OCR1A
   TCCR1B = (1 << WGM13) | (1 << WGM12); //meaning all WGM1[3:0] bits set

   //Register that will contain the value to be compared with
   OCR1A = 10000; //10k counts according to prescaler of 8 for 5ms delay, 5ms / (1/(16Mhz/8)) = 10k counts

   TIMSK1 = 1 << OCIE1A;
   sei();

   for(;;){
      if(counter == COUNT)
         PORTB ^= (1 << PB1);
   }
   return 0;
}

ISR(TIMER1_COMPA_vect){
   if(!(PIND & (1 << PD2))){
      if( (++counter >= COUNT) || (counter < 0) )
         counter = 0;
   }else{
      counter--;
   }
}

 

But still not working either!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How can counter be less than 0? You can simplify your logic by using a downcounter. If he pin is high, then counter = COUNT else if counter > 0 then counter—

If counter equal 0 then the pin has been sampled as low for COUNT times. Simples.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
How can counter be less than 0? You can simplify your logic by using a downcounter. If he pin is high, then counter = COUNT else if counter > 0 then counter— If counter equal 0 then the pin has been sampled as low for COUNT times. Simples.

 

A variable can contain sign or not, right? That's why there are signed and unsigned types of variables. Despite of that I just tried to follow avrcandies instructions and he said specifically to not let it go under 0.

 

I think I found a bug on my test program. I used in main() "if counter == COUNT" and maybe I should use '>' instead of '=='.

 

I'm sorry that I'm changing what I'm trying to do but I'm following suggestions and some of you says to do "this" and others says to do "that" and this might become a bit messy but I?ll try to follow up!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:

Either ways, .hex file content is this:

 

Thankyou.

 

 

PsySc0rpi0n wrote:

But still not working either!

 

OK, so I take your hex file posted above and use it to program a 328P sitting in a known working test PCB (the one I posted a picture of earlier). The PCB uses active low switches and active low LEDs. I make NO changes to the file at all.

 

IT WORKS!

 

If I press the switch connected to PortD.2 it toggles on and off the LED connected to PortB.4. If I press the switch on PortD.3 the LED on B.5 toggles. 

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brian Fairchild wrote:

PsySc0rpi0n wrote:

Either ways, .hex file content is this:

 

Thankyou.

 

 

PsySc0rpi0n wrote:

But still not working either!

 

OK, so I take your hex file posted above and use it to program a 328P sitting in a known working test PCB (the one I posted a picture of earlier). The PCB uses active low switches and active low LEDs. I make NO changes to the file at all.

 

IT WORKS!

 

If I press the switch connected to PortD.2 it toggles on and off the LED connected to PortB.4. If I press the switch on PortD.3 the LED on B.5 toggles. 

 

Why you are talking about PortB.4 and PortB.5? I thought it was PB1 or PortB.1. That's what I have in my code.

 

Edited;

Ah ok, I think any PortB pin should work as it was the whole port set as output!

Last Edited: Sat. Jul 14, 2018 - 01:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:

Why you are talking about PortB.4 and PortB.5? I thought it was PB1 or PortB.1. That's what I have in my code.

 

My bad, I had the jumper cable off by a row. It's actually PortB.2 and Port B.3 (pins 16 and 17 on the chip)

 

I think you misunderstand the return value from get_key_press(). It returns a bit mask of which keys are pressed within your mask value. So if you send 0x0C to it, it will look at bits/switches 2 and 3 and return the state of those switches, once debounced, in bits 2 and 3.

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brian Fairchild wrote:

PsySc0rpi0n wrote:

Why you are talking about PortB.4 and PortB.5? I thought it was PB1 or PortB.1. That's what I have in my code.

 

My bad, I had the jumper cable off by a row. It's actually PortB.2 and Port B.3 (pins 16 and 17 on the chip)

 

I think you misunderstand the return value from get_key_press(). It returns a bit mask of which keys are pressed within your mask value. So if you send 0x0C to it, it will look at bits/switches 2 and 3 and return the state of those switches, once debounced, in bits 2 and 3.

 

Regardless of that, the code is still not working here! But I'm at the moment trying to do what avrcandies said!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quit using concatenated logic, keep it simple & do one thing at a time--not 5 things in one statement!

 

if (pind & (1<<PD2))  {
    if (counter<COUNT)
       counter++;
    }

else

   if (counter>0)
      counter--;

In main DO NOT check for =  check for >=...the count will be increasing rapidly & you will miss the exact matching  & wonder why you never get a hit.

You must pick a check that is perhaps halfway to the max limit  (COUNT/2)  ..NOT the max, or you will lose holding debounce protection (like when you have a weak finger)

 

Simple Summary: 

When the button not pushed, counts down to zero limit

When the button is pushed, counts up to MAX limit

When the count>= MAX/2 , you have a valid press....easy??   

 

 

 

When in the dark remember-the future looks brighter than ever.

Last Edited: Sat. Jul 14, 2018 - 08:21 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Also I'd reduce it to one button not two for starters so not 0x0C but a mask with just one bit set until you understand it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
Regardless of that, the code is still not working here!

So your code works here on my known working good hardware but not on your hardware. What does that suggest?

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, still about avrcandies suggestion, I made the code to work but I didn't understood something.

 

The code is as follows:

 

//Datasheet used
//http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega328_P%20AVR%20MCU%20with%20picoPower%20Technology%20Data%20Sheet%2040001984A.pdf

#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>

#define COUNT 100

volatile uint8_t counter = 0;

int main(void){

   DDRB = 0xff;


   //Using Timer1, page 152
   //Prescaler to be used, if needed, Table 20-7, page 177
   TCCR1B = (1 << CS11); //prescaler of 8

   //Operation mode, Table 20-6, pages 175 and 176
   //set mode to CTC, TOP value of OCR1A, WGM1[3:0] -> 0100
   TCCR1A &= ~((1 << WGM11) | (1 << WGM10)); // WGM11 and WGM10 unset
   TCCR1B |= (1 << WGM12);   // WGM12 set
   TCCR1B &= ~(1 << WGM13 ); // WGM13 unset

   //Register that will contain the value to be compared with
   OCR1A = 10000; //10k counts according to prescaler of 8 for 5ms (200Hz) delay, 5ms / (1/(16Mhz/8)) = 10k counts

   //Enable Compare Output A mode
   TIMSK1 = (1 << OCIE1A);

   for(;;){
      if(TCNT1 & (1 << 12))
         PORTB = (1 << PB1);
      else
         PORTB = 0;
   }
   return 0;
}

 

What I didn't understood is why I had to read bit 12 of TCNT1 to get the 200Hz on the scope. I did this by trial and error!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brian Fairchild wrote:
PsySc0rpi0n wrote:
Regardless of that, the code is still not working here!
So your code works here on my known working good hardware but not on your hardware. What does that suggest?

 

My hardware is working with other codes! I have no idea why that code is not working here! But yes, it suggests my hardware is probably not matching the code. I wonder why!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, apparently it's not reasonable to try to do that.

 

Anyway, I made it working for 200Hz using interrupts. Here is the code:

 

//Datasheet used
//http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega328_P%20AVR%20MCU%20with%20picoPower%20Technology%20Data%20Sheet%2040001984A.pdf

#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>

#define COUNT 100

volatile uint8_t counter = 0;

int main(void){

   DDRB = 0xff;

   //Using Timer1, page 152
   //Prescaler to be used, if needed, Table 20-7, page 177
   TCCR1B = (1 << CS11) | (1 << CS10); //prescaler of 64

   //Operation mode, Table 20-6, pages 175 and 176
   //set mode to CTC, TOP value of OCR1A, WGM1[3:0] -> 0100
   TCCR1A &= ~((1 << WGM11) | (1 << WGM10)); // WGM11 and WGM10 unset
   TCCR1B |= (1 << WGM12);   // WGM12 set
   TCCR1B &= ~(1 << WGM13 ); // WGM13 unset

   //Register that will contain the value to be compared with
   OCR1A = 625; //625 counts according to prescaler of 64 for 5ms (200Hz) delay, 2.5ms / (1/(16Mhz/64)) = 625 counts

   //Enable Compare Output A mode
   TIMSK1 = (1 << OCIE1A);
   sei();
   for(;;){
   }
   return 0;
}

ISR(TIMER1_COMPA_vect){
   PORTB ^= (1 << PB1);
}

 

Last Edited: Sat. Jul 14, 2018 - 10:41 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
ISR(TIMER1_COMPA_vect){
   PORTB ^= (1 << PB1);
}

 

remember  this flipping will provide 1/2 the irq freq.  An irq of 1000Hz will show as 500 pulses per sec (1000 edges going up & down)

 

desired 200Hz irq (edges) will show as 100Hz pulses.  This hidden factor of two often knocks programmers out of their car seats.

When in the dark remember-the future looks brighter than ever.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:

ISR(TIMER1_COMPA_vect){
   PORTB ^= (1 << PB1);
}

 

remember  this flipping will provide 1/2 the irq freq.  An irq of 1000Hz will show as 500 pulses per sec (1000 edges going up & down)

 

desired 200Hz irq (edges) will show as 100Hz pulses.  This hidden factor of two often knocks programmers out of their car seats.

Thanks for warning. I noticed it and that's why OCR1A is set with 625 and not the value that results in 5ms delay which would be 1250. 625 is actually for 2.5ms delay. Tomorrow I'll proceed to next step.

Last Edited: Sat. Jul 14, 2018 - 11:57 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 I noticed it and that's why OCR1A is set with 625

Sorry chief, you got it backwards.   We want 200 irqs/sec (led toggle edges)...  If you toggle at 4 times a sec (4Hz), due to toggling you'd see the led flash at 2Hz.

So 200 toggles a sec will flash the led at 100Hz.   So if you scope it beware ONLY THEN so you don't say why don't I see 200Hz?

 

Anyhow, 200 something a second is 5ms  (0.005 sec) separation between them.

 

Note dividing by period is same as mult by freq, which is 16000000/64

 

So the count needed is [0.005*16000000/64] minus 1  or 1249  ...this will check the switch 200 times a sec--one SwitchAcount  and SwitchBcount every 5ms

 

 

 

 

 

     

When in the dark remember-the future looks brighter than ever.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, so if the idea is the 200 times a second, that will be in fact 100Hz and 1249 counts. I just need to change the counting value in OCR1A.

 

Now that this in between task is done, I'm going back to the code from post #19 and try again to make it work!

 

And to make it clear, please confirm or deny each of the following:

 

1 - Active-Low means that "something happens" when I short whatever it is to GND. In other words, the normal state is at about 5V, and when a button (or whatever is pressed), the voltage goes momentarily to 0V.

2 - Active-High means that "something happens" when I short whatever it is to +5VDC. In other words, the normal state is at about 0V, and when a button (or whatever is pressed), the voltage goes momentarily to 5V.

3 - The code in question (from post #19) is supposed to be for hardware in Active-Low or Active-High?

4 - The LED the will toggle in 3, is to be Active-Low or Active-High?

 

Thanks

Psy

Last Edited: Sun. Jul 15, 2018 - 08:54 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, I did the following test with the code from post #19.

 

I commented the following line in main():

LED_OUTPUT ^= get_key_press(0x0c);

 

and added the following to check if timer was running:

if(TIFR0 & (1 << TOV0))
         PORTB ^= (1 << PB1);

 

I'm not sure this is the best approach but I get a frequency on scope of 61Hz. So, even if this is not the best was to check if timer is overflowing and triggering an interrupt, at least I know that TOV0 is being set. That tells me the timer is running, right?

 

And I have another question about the code, or  better, the comments in the code. Why in the line where the prescaler is set, there is a comment saying "divide 256 * 256". What is this supposed to mean?

 

Also in my case, I'm not sure if this frequency of 61Hz is exactly the frequency the count gives. I mean, if I use a prescaler of 256, I get 16Mhz/256 = 62.5Khz. This means a tick (or count) every 1/62500 of a second or 16us. As this is an 8 bit counter, the overflow occurs every 256 ticks, meaning after 16us * 256 = 4096 us. This means a frequency of 244.14Hz. On scope will show up a half of this value due to toggling. Curiously the frequency showing up on scope is half of hlaf of 244Hz, I mean 61Hz * 4 = 244Hz.

 

So where the 61Hz comes from? Or am I going wrong with the math?

Last Edited: Sun. Jul 15, 2018 - 09:58 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, so if the idea is the 200 times a second, that will be in fact 100Hz and 1249 counts. I just need to change the counting value in OCR1A.

Now that this in between task is done, I'm going back to the code from post #19 and try again to make it work!

 

Does the 200Hz debounce work?  Once you have the IRQ running, it is only a few minutes to have it all ready.

Its like you are wandering in the AVR desert, going from town to town

 

So where the 61Hz comes from

if you are getting 16000000/256/256=244 irqs per second, why do you think you see a 122 square wave?  Are you sure you see 61Hz?

could be, since you are checking the irqflag in main, you only catch it half the time (since it is immediately handled)...that would make tha apparent freq less.

 

When in the dark remember-the future looks brighter than ever.

Last Edited: Sun. Jul 15, 2018 - 03:30 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:

Ok, so if the idea is the 200 times a second, that will be in fact 100Hz and 1249 counts. I just need to change the counting value in OCR1A.

Now that this in between task is done, I'm going back to the code from post #19 and try again to make it work!

 

Does the 200Hz debounce work?  Once you have the IRQ running, it is only a few minutes to have it all ready.

Its like you are wandering in the AVR desert, going from town to town

 

So where the 61Hz comes from

if you are getting 16000000/256/256=244 irqs per second, why do you think you see a 122 square wave?  Are you sure you see 61Hz?

could be, since you are checking the irqflag in main, you only catch it half the time (since it is immediately handled)...that would make tha apparent freq less.

 

 

Indeed... I made the toggle inside the ISR vector and it shows correct frequency! 122Hz is because of the toggling thing.

About the original code from post #19, now I need to find a way of checking if it is working!

 

And the math I do is:

 

Crystal Freq / Prescaler factor

16Mhz / 256 = 62.5Khz

 

This means 1/62.5Khz seconds = 16us for each increment in TCNT0.

As Timer0 is 8-bit, the overflow takes 16us * 256 = 4096us to occur.

This means the flag will be set at a rate of 1/4096us = 244.14Hz.

I'm just not sure how it makes of this a 50% Duty Cycle and why  this is not more like a pulse and then the TVO0 flag would be set to 0 because the ISR routine is just a line of code and the remaining time was at 0V.

Something like this:

____|____|____|____

 

where each '|' is the TOV0 is set to 1 and immediately set to 0 because the ISR is just that line of code.

Instead, we have something like:

 

__|--|__|--|__|--|__

 

 

Anyway, I want to move on!

 

 

So, about the code of post #19, I'm going to try to use only a push-button at PD2 and a LED at PB1.

Push-Button is Active-Low. Meaning that the pin is using a 10k ohm pull-up resistor and the push-button has one lead to that uC pin and the other lead to GND. When I press the push-button, it sets 0V at PD2.

LED at PB1 has one lead (+ lead) connected to PB1 and the other lead (- lead) connected to a 470 ohm resistor that is connected to GND.

 

Is this the way the hardware should be set to work correctly with the code? 

Last Edited: Sun. Jul 15, 2018 - 05:05 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Where is that link to a post where there was sort of a table with the current result of all the bitwise operations taking place inside the ISR of code from post #19? I can't find it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have a feeling it was a link I gave to an analysis of danni's code by Johan Ekdahl

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
I have a feeling it was a link I gave to an analysis of danni's code by Johan Ekdahl

Yes it was! I think the code is working and the return of the get_key_press() is just the address of the button pressed after debounced, right? In that case, if I want a LED to light ON I need to have a LED connected to the pin the push-button is connected to, no?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I found the link:

 

Here for future reference.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Personally, I think you should stick with the simple counter method---why? it is simple to understand and debug & get working.  Getting the IRQ running is the hardest part & you already have that going (with a few fumbles along the way).

 

The other method is (Danni) great, but you will fall into an evil cave & need rescued over & over because it has more complex/convoluted details. Even though what you have should already be working, it is not--so you are about to wander into that cave seeking many solutions from the medicine man.

 

Soon you will be in the winners circle, lapping up the adulation,  big prize money, and maybe a free t-shirt.

 

When in the dark remember-the future looks brighter than ever.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, if I get my questions answered I bet with myself I'll get there! What I can't do is changing my mind constantly which I already did to try to accomplish your last suggestion (the 200Hz thing). I need to stick to this and I don't need to understand all and every detail of the code. I'll be happy to just understand the way it works so that I can adapt it to my code! That's all.

 

And I have a couple of questions about it! I was reading the walkthrough I just posted about and it's said that the variables all starts with 0. But any of the variables were assigned with a 0. So how do we know they don't have trash by the start of the program?

Another question is that one I made above about the return value of that function!

 

If I get these answer I might start doing the thing on my own I guess!

Last Edited: Mon. Jul 16, 2018 - 07:24 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I was going to say that Danni's code is not rocket science though I guess it is a bit. But anyway all it ultimately does is monitor between 1 and 8 bits in a port. You pass in a mask to say which and how many you want to know about. In your case the mask value 0x0C means "two bits, bits 2 and 3 (counting 0 to 7)" it then returns 1 bits in bit position 2 or 3 or both or neither to indicate which of the two are pressed. So it will return 0x00 if neither are pressed, 0x04 if only bit 2 is pressed, 0x08 if only bit 3 is pressed or 0x0C if both 2 and 3 are pressed. It really is as simple as that (and hence not rocket science - even if it really is!)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So, in my case, I'll have to check when any of the buttons is pressed to take an action when it is, right?

Pages