Closed JohnMac1234 closed 3 years ago
Hi JohnMac,
Sorry for the delay - was quite busy last days and it slipped of my agenda 😒 Will look into this issue today.
To be able to understand the problem in detail, could you add a whole sketch that shows the problem.
That said, I assume the following happens. The PCF8574 interrupt is triggered when one or more pins change. Initially the value of the pins are either 0x00 or 0xFF. So if a pin is pressed no value will change.
After the call to getKey, the pins are set 4 as output and 4 as input. (0xF0) If now a pin is pressed the change is detected and the interrupt is triggered.
This sounds great enough to look into it to get a better support for it. Might take a few days.
Thanks for pointing out.
it just needs a _read(0xF0) in the begin() functions, to make interrupts possible. Expect an update today.
@JohnMac1234 Experimental interrupt support added in 0.2.1 release. Please verify it works without adding
uint8_t idx = keyPad.getKey();
@RobTillaart Hi Rob Here is the original code
// Arduino Nano select old bootloader
// Display 2002 using I2C & Keypad 4x4 using Waveshare GPIO to I2C
// https://www.instructables.com/How-to-Measure-Angle-With-MPU-6050GY-521/ GY-521
#include "Wire.h" // I2C Arduino
#include "I2CKeyPad.h" // I2CKeyPad by Rob Tillaart version 0.1.2
#include "LiquidCrystal_I2C.h" // LiquidCrystalI2C by Frank de Brabander version 1.1.2
#include <Ultrasonic.h> // Ultrasonic by Erick Samoes Installed from Arduino library
LiquidCrystal_I2C lcd(0x27, 20, 4); // lcd address is 0x27, 20x4 display
Ultrasonic ultrasonic(12, 13); // Pass as a parameter the trigger 12 and echo pin 13
int distance;
const uint8_t KEYPAD_ADDRESS = 0x20; // Waveshare GPIO PCF8574T I2C Keypad module is set to 0x20
char currentKey;
I2CKeyPad keyPad;
const byte ROWS = 4; // four rows
const byte COLS = 4; // four columns
char keys[ROWS][COLS] =
{
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3, 2};
const int len_key = 5;
char master_key[len_key] = {'1','2','3','4','1'};
char attempt_key[len_key];
const int MPU_addr=0x68;
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;
int minVal=265;
int maxVal=402;
double x;
double y;
double z;
int Interrupt_Pin = 3;
volatile int InterruptHappened;
//*********************************************************************************************************
void setup()
{
pinMode(Interrupt_Pin,INPUT_PULLUP); // Set to input to use interrupt and turn on pull up resistors 20k to 50k
attachInterrupt(digitalPinToInterrupt(Interrupt_Pin), buttonPressed,FALLING); // function for creating external interrupts at pin2 on Rising (LOW to HIGH)
Wire.begin();
Wire.setClock(400000);
Wire.beginTransmission(MPU_addr);
Wire.write(0x6B);
Wire.write(0);
Wire.endTransmission(true);
lcd.init();
lcd.backlight();
lcd.setCursor(0,0);
InterruptHappened = 0;
keyPad.begin(KEYPAD_ADDRESS);
// adding this command here gets interrupts working on power up. uint8_t idx = keyPad.getKey();
MainDisplay();
}
//*********************************************************************************************************
void loop()
{
char keys[] = "123A456B789C*0#DNF"; // N = Nokey, F = Fail
if (InterruptHappened == 1)
{
InterruptHappened = 0; // Reset flag
uint8_t idx = keyPad.getKey();
currentKey = (keys[idx]); // save current key
switch (currentKey)
{
case 'D':
Distance();
break;
case 'A':
Angles();
break;
}
}
}
//*********************************************************************************************************
void buttonPressed()
{
InterruptHappened = 1; // Set flag to highlight interrupt
}
//*********************************************************************************************************
void Angles()
{
for (int i = 0; i <= 50; i++)
{
Wire.beginTransmission(MPU_addr);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU_addr,14,true);
AcX=Wire.read()<<8|Wire.read();
AcY=Wire.read()<<8|Wire.read();
AcZ=Wire.read()<<8|Wire.read();
int xAng = map(AcX,minVal,maxVal,-90,90);
int yAng = map(AcY,minVal,maxVal,-90,90);
int zAng = map(AcZ,minVal,maxVal,-90,90);
x= RAD_TO_DEG * (atan2(-yAng, -zAng)+PI);
y= RAD_TO_DEG * (atan2(-xAng, -zAng)+PI);
z= RAD_TO_DEG * (atan2(-yAng, -xAng)+PI);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Angle X = ");
lcd.print(x);
lcd.setCursor(0,2);
lcd.print("Angle Y = ");
lcd.print(y);
delay(2000);
}
MainDisplay();
}
//*********************************************************************************************************
void Distance()
{
for (int i= 0; i <=20; i++)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Distance in cm");
lcd.setCursor(0, 1);
distance = ultrasonic.read();
lcd.print(distance);
delay(1000);
}
MainDisplay();
}
//*********************************************************************************************************
void MainDisplay()
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Press A for Angles");
lcd.setCursor(0,1);
lcd.print("Press D for Distance");
}
//**********************************************************************************************************
I've tried compiling with 0.2.0 and 0.2.1 but both give an error on the line
I2CKeyPad keyPad;
The error is 'no matching function for call to 'I2CKeyPad()'
I go back to 0.1.2 and it compiles ok.
The signature of the functions have (breaking) changed to support multiple instances of Wire. (sorry)
I2CKeyPad keyPad(KEYPAD_ADDRESS);
.....
keyPad.begin(); // so the address parameter is moved to he constructor..)
Hi Rob
The interrupt at power up now works great with 0.2.1, no need for an initial read of keypad. Thanks for your help Rob
You are welcome, you may close the issue ;)
FYI - I added an interrupt example (it is only in the master branch, not in a release)
Interrupt example worked ok. Only thing I noticed was the notes at the start says the interrupt is on pin 2 but the code uses pin 3.
You're right, ==> In case of a difference between code and comments code always wins.
I'll leave it as an exercise in reading for the users.
BTW, I tested if it was possible to read the keypad in the interrupt routine, but I did not succeed.
If you have other ideas / improvements for the library (or one of the others), just open a new issue.
Thanks again for this idea!,
Hi Rob, I'm using the Waveshare GPIO PCF8574T connected to a 4x4 keypad with I2CKeypad.h connected to a NANO.
I placed keyPad.begin(KEYPAD_ADDRESS); in the setup() section and uint8_t idx = keyPad.getKey(); in the loop() section waiting for an interrupt to occur. i.e. if (InterruptHappened == 1) { InterruptHappened = 0; // Reset flag
uint8_t idx = keyPad.getKey(); currentKey = (keys[idx]); // save current key switch (currentKey) etc
However on power up no interrupts occured when a key was pressed. But when I manually temporarily pulled the interrupt low at the start the interrupts worked on each subsequent key press. It was as if that first key press(es) on power up wasn't being detected.
I then found out that if I added the command "uint8_t idx = keyPad.getKey();" into the setup() section the interrupts started working from power up. So it would appear that the first "uint8_t idx = keyPad.getKey();" is needed to initialise the interrupts at power up.
It seems odd to have to poll the I2C keypad to get the interrupt working when the interrupt is there to not have to poll for key presses. I am new to the Arduino so I may be doing something wrong in the setup but thought I should mention this. Thanks John