It was surprising to see that there is no single library for using I2c keypad & LCD using PCF8574 expander. I came across different library for each purpose conflicting when used in single project.
If anybody know a solution for this please guide me. I am willing to use 4x4 keypad & 20x4 LCD on single I2C for the blue pill STM32.
If you mean both things together in one library, then I think you will not found anything. Simply because there are many combinations - keypads, rotary encoders, buttons and so on.
Thanks for the reply. I agree both library work but individually. But as I add header of <TextLcd.h> with PCF8574.h I do see an error " Error: Expected a declaration PCF8574 io(PB_8,PB_9,0x40)". I also didn’t find any example having both library together.
Yeah, there seems to be a conflict between macros from TextLCD with same name as Class name - PCF8574.
I made a fork of original and changed Class name to PCF8574IO and I also reworked constructor for I2C object instead of I2C pins
Hi Jan,
I do really appreciate your efforts & help.
With your updated fork code do get compile.
However I do see the interrupt doesn’t work for the keypad.
Here is the complete code for bluepill i.e. Nucleo-F103RB for mbed:
#include "mbed.h"
#include "PCF8574.h"
#include <TextLCD.h>
#define BAUD 9600
I2C i2cBus(PB_7, PB_6);
TextLCD_I2C lcd(&i2cBus, 0x4E, TextLCD::LCD20x4);
PCF8574IO io(&i2cBus,0x40);
InterruptIn event(PB_5);
Serial pc(PA_9, PA_10);
int data1 , data2;
void display(int data)
{
switch (data)
{
case 238: pc.printf("SW1 \n\r"); break;
case 237: pc.printf("SW2 \n\r"); break;
case 235: pc.printf("SW3 \n\r"); break;
case 231: pc.printf("SW4 \n\r"); break;
case 222: pc.printf("SW5 \n\r"); break;
case 221: pc.printf("SW6 \n\r"); break;
case 219: pc.printf("SW7 \n\r"); break;
case 215: pc.printf("SW8 \n\r"); break;
case 190: pc.printf("SW9 \n\r"); break;
case 189: pc.printf("SW10 \n\r"); break;
case 187: pc.printf("SW11 \n\r"); break;
case 183: pc.printf("SW12 \n\r"); break;
case 126: pc.printf("SW13 \n\r"); break;
case 125: pc.printf("SW14 \n\r"); break;
case 123: pc.printf("SW15 \n\r"); break;
case 119: pc.printf("SW16 \n\r"); break;
}
lcd.locate(0,0);
lcd.printf("KEY :%d",data);
}
void trigger()
{
//event.fall(NULL);
//printf("triggered!\n");
io.write(0x0f);
data1 = io.read();
io.write(0xf0);
data2 = io.read();
display(data1+data2);
//wait(0.2);
//event.fall(&trigger);
}
int main()
{
data1=data2=0;
event.mode(PullUp);
pc.printf("Start\n\r");
event.fall(&trigger);
//event.rise(&trigger);
lcd.locate(0,0);
lcd.printf("KEY :%d",data1);
while(1)
{
}
}
But by polling the key instead following code works perfectly :
#include "mbed.h"
#include "PCF8574.h"
#include <TextLCD.h>
I2C i2cBus(PB_7, PB_6);
TextLCD_I2C lcd(&i2cBus, 0x4E, TextLCD::LCD20x4);
PCF8574IO io(&i2cBus,0x40);
Serial pc(PA_9, PA_10);
int data1 , data2;
char key;
char GetKey()
{
io.write(0x0f);
data1 = io.read();
io.write(0xf0);
data2 = io.read();
switch (data1+data2)
{
case 235: key = '0'; break;
case 119: key = '1'; break;
case 123: key = '2'; break;
case 125: key = '3'; break;
case 183: key = '4'; break;
case 187: key = '5'; break;
case 189: key = '6'; break;
case 215: key = '7'; break;
case 219: key = '8'; break;
case 221: key = '9'; break;
case 126: key = 'A'; break;
case 190: key = 'B'; break;
case 222: key = 'C'; break;
case 238: key = 'D'; break;
case 231: key = '*'; break;
case 237: key = '#'; break;
case 255: key = 'N'; break;
}
return(key);
}
int main()
{
data1=data2=0;
pc.printf("Start\n\r");
lcd.locate(0,0);
lcd.printf("KEY :%d",data1);
while(1)
{
key = GetKey();
if(key != 'N')
{
lcd.locate(0,0);
lcd.printf("KEY :%c",key);
}
}
}
that is great.
I know nothing about your Keypad and connection with Expander, but I suppose you have the pin PB_5 connected to INT pin of the Expander. The INT pin also must have Pull-up resistor to Vcc, so internal pull-up resistor can be not enough.
You probably use the Bare Metal Mbed OS profile, but letting done all the work in ISR is not a good practice.
Great…the interrupt is working ! Its definitely better than polling what I was doing earlier !
I am also using an I2C MCP20338 liabrary & I do see it’s conflicting with the TextLCD library. The program do get compiled if I exclude MCP20338 liabrary or TextLCD, The code is given below:
#include "mbed.h"
#include "PCF8574.h"
#include <TextLCD.h>
I2C i2cBus(PB_7, PB_6);
TextLCD_I2C lcd(&i2cBus, 0x4E, TextLCD::LCD20x4);
PCF8574IO io(&i2cBus,0x40);
InterruptIn event(PB_5);
Serial pc(PA_9, PA_10);
char key;
bool KeyPressed = 0;
void GetKey()
{
char data1=0;
char data2=0;
io.write(0x0f);
data1 = io.read();
io.write(0xf0);
data2 = io.read();
switch (data1+data2)
{
case 235: key = '0'; break;
case 119: key = '1'; break;
case 123: key = '2'; break;
case 125: key = '3'; break;
case 183: key = '4'; break;
case 187: key = '5'; break;
case 189: key = '6'; break;
case 215: key = '7'; break;
case 219: key = '8'; break;
case 221: key = '9'; break;
case 126: key = 'A'; break;
case 190: key = 'B'; break;
case 222: key = 'C'; break;
case 238: key = 'D'; break;
case 231: key = '*'; break;
case 237: key = '#'; break;
case 255: key = 'N'; break;
}
if(key != 'N')
{
lcd.locate(0,0);
lcd.printf("KEY :%c",key);
}
KeyPressed = 0;
}
void trigger()
{
if(!KeyPressed) KeyPressed = 1;
}
int main()
{
pc.printf("Start\n\r");
event.mode(PullUp);
event.fall(&trigger);
lcd.locate(0,0);
lcd.printf("KEY :");
while(1)
{
if(KeyPressed) GetKey();
}
}
As I include the MCP20338 library I do get an error “Error: Expected either a definition or a tag name in “MCP23008/MCP23008.hpp”, Line: 8, Col: 8”
Well it got working by another corrected library : MCP23008_I2C