Hi as part of a bigger project I need to be able to read a simple keypad with 5 buttons. I found this library, but i did not used it because it uses DigitalRead. I decided to write my own code with port accessing, but using the same basic principle. Here is what I have:
int main() {
DDRB = 0b10000000;
PORTB = 0b00011111;
Serial.begin(9600);
while(true)
{
if (pressedButton(1))
{
PORTB |= 0b10000000;
Serial.println("button 1 pressed");
}
else
{
PORTB &= 0b011111111;
}
}
}
bool pressedButton(byte buttonNum)
{
byte currentState = PINB<<3;
bool _isPressed = false;
byte _button = (0b00000001 << (buttonNum + 2))^0b11111000;
byte debaunceTime = 500; // debounce time in ms
static bool debaunceActive = false;
static unsigned long debaunceUntil;
if((currentState == _button) && (debaunceActive == false))
{
_isPressed = true;
//start debaunce
debaunceUntil = millis() + debaunceTime;
debaunceActive = true;
}
else if(millis() < debaunceUntil) //button is still pressed and debaunce time has passed
{
// do nothing
}
else
{
debaunceActive = false;
}
return _isPressed;
}
since I don't currently have arduino mega at hand I use Proteus to simulate the circuit. This is the result:
when I press the button the LED turns on and I get just the letter "b" in the console, when I release it and press it again nothing changes, the LED does not turn off and no output to the console.
I don't need information for toggle and release of the button, just pressing, and if held down to return true every half a second.
I guess there is something verry simple that I am missing, I will really appreciate your help.
That was a complicated way of reading 5 buttons and now You are lost. That's typical for sophisticated coding.
No input is saved. I doubt anything is saved. Why?
No, it just takes much more processing time, compared t direct port access. The project I am building is a 3 phase VFD, and is quite time sensitive, so I am trying to optimise the code as much as possible to have more processing time for the important stuff, like measuring sensors, calculating errors and PID regulation. Also Arduino mega has a lot of pins that are not wired and not mapped and can't be used with DigitalRead
I'll disagree with that: it's anyone's prerogative to suggest that your solution's cr@p in the first place, rather than try help you kluge it into submission.
Maybe off the "immediate" topic, but not off the topic of helping you reach a solution to the actual problem.
When i simulate it with Proteus it works fine, but when I add it in the main program, it craps out. When I press a button it prints one line, when press the same button again nothing happens, and this is the same for the 5 buttons. With every single one I have one printout and after that the buttons don't do anything.
This is the full program:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <Button.h>
const unsigned int sineValues[] PROGMEM = {
0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 79, 85, 91, 97, 103, 109,
....
//array of 2024 elements containing a sine wave with max value of 3992, deleted for reducing the length of the post
....
145, 139, 133, 127, 121, 115, 109, 103, 97, 91, 85, 79, 72, 66, 60, 54, 48, 42, 36, 30, 24, 18, 12, 6
};
const int valNumber = sizeof(sineValues)/2; //sizeof returns number of bites used, int values use 2 bytes
const unsigned int periodPWM = 3922;
static double voltageFactor = 1;
static int desiredFrequency = 49;
Button buttonLeft(37);
Button buttonEnter(36);
Button buttonRight(35);
Button buttonStart(34);
Button buttonStop(33);
int main(){
TimerSetup();
Serial.begin(115200);
buttonLeft.begin();
buttonEnter.begin();
buttonRight.begin();
buttonStart.begin();
buttonStop.begin();
while(true){
if (buttonLeft.pressed())
Serial.println("Button LEFT pressed");
else if (buttonEnter.pressed())
Serial.println("Button ENTER pressed");
else if (buttonRight.pressed())
Serial.println("Button RIGHT pressed");
else if (buttonStart.pressed())
Serial.println("Button START pressed");
else if (buttonStop.pressed())
Serial.println("Button STOP pressed");
}
}
ISR(TIMER3_OVF_vect){ //Change the timer value when counter goes to TOP
//PORTB ^= 0b00000001;
static unsigned int phase2Offset = valNumber/3*2;
static unsigned int phase3Offset = valNumber/3;
static bool delay1;
static bool delay2;
static bool delay3;
static float currentStep1 = 0;
static float currentStep2 = phase2Offset;
static float currentStep3 = phase3Offset;
static float increment = ((float)desiredFrequency/100)*102;
if(delay1 == true){
PORTB ^= 0b00000011;
delay1 = false;
}
else if(delay2 == true){
PORTB ^= 0b00001100;
delay2 = false;
}
else if(delay3 == true ){
PORTB ^= 0b00110000;
delay3 = false;
}
else if(currentStep1 >= valNumber){ //when _step gets to the last sine value change pins and zero _step
//TCCR3A ^= 0b10100000;
currentStep1 = 0;
delay1 = true;
}
else if(currentStep2 >= valNumber){ //when _step gets to the last sine value change pins and zero _step
//TCCR3A ^= 0b10100000;
currentStep2 = 0;
delay2 = true;
}
else if(currentStep3 >= valNumber){ //when _step gets to the last sine value change pins and zero _step
//TCCR3A ^= 0b10100000;
currentStep3 = 0;
delay3 = true;
}
//ICR1 = periodPWM*frequencyFactor;
OCR3A = (pgm_read_word_near(sineValues + (int)currentStep1))*voltageFactor;
OCR3B = (pgm_read_word_near(sineValues + (int)currentStep2))*voltageFactor;
OCR3C = (pgm_read_word_near(sineValues + (int)currentStep3))*voltageFactor;
currentStep1 += increment;
currentStep2 += increment;
currentStep3 += increment;
//PORTB ^= 0b00000001;
}
void TimerSetup(){
//Setup for timer3
TCCR3A = 0b10101010;
TCCR3B = 0b00011001;
TIMSK3 = 0b00000001;
ICR3 = periodPWM;
DDRB = 0b00111111;
DDRE = 0b00111000;
PORTB = 0b00100101;
//Setup for timer4
TCCR4A = 0b00000000;
TCCR4B = 0b00000010; // 0bXXXXX010 means internal clock with clk/8 prescaler
TIMSK4 = 0b00100000; //Input capture interrupt enabled
sei();
}
ISR(TIMER4_CAPT_vect){
static unsigned int currentTime;
static unsigned int lastTime=0;
//const float _step = 0.5; //one increment of the timer4 is equal to 0.5 us
int freq;
float timePeriod;
currentTime = ICR4;
if(lastTime > currentTime){ //if the timer oveflowed add the difference
timePeriod = (0xFFFF-lastTime+currentTime)/2; // one increment of the timer4 is equal to 0.5 us, by dividing by 2 the total period of the pulse is recieved in us
}
else{
timePeriod = (currentTime-lastTime)/2;
}
timePeriod /=1000; // convert to kHz
lastTime = currentTime;
freq = 1/(timePeriod/1000); //freqency in Hz
//Serial.println(freq);
I'll be damned...
It turned out I should not use int main(). when I changed the code to the standard format void setup() and void loop() everything started to work properly, even the original idea with direct port access. The reason for this is the way the compiler works.