Arduino program hurdle I can't cross

Howdy!
I have been wracking my brains on coming up with a two wire solution for my project.
The Project: gut out the proprietary electronics out of a Neopost Si-30 mail folder/inserter and use an Arduino MEGA2560 (Elegoo's ) as the beginning of it being an inserter. My first step was to build a hardware platform to test out the DC motors, stepper motors, flag sensors, linear hall effect sensors, and solenoids, using as few pins as possible.
I'm using a 20x4 Character I2C LCD with address 0x3F (the unusual address is due to difference between NXP and someone else's PCF8574.) I needed a 4x4 matrix keypad, also I2C like the folks at BrainyBits (A Keypad and LCD with only 2 Pins?! No problem with the I2C Protocol!
Oct 25, 2020) . And, I wanted an I2C 8-ch relay module using another of the PCF8574 modules.

This photo is from Instructables (PCF8574 GPIO Extender used with Arduino and NodeMCU
By Tarantula3 in CircuitsArduino).
My Code is as follows:


/*
 * collected by Ricky Robbins from examples from:
 * // I2C Keypad library by Rob Tillaart https://github.com/RobTillaart/I2CKeyPad
 * //LiquidCrystal_I2C maintained by Marco Schwartz https://github.com/johnrickman/LiquidCrystal_I2C
 * 
 * 8 Channel Electromagnetic relay module board 5.0V 3.3V / 700mA       
 * I2C expander on PCF8574 or PCF8574A chip                                       
 *  Logic level "0" ON relay, logic level "1" OFF relay 
 * works as is 7/22/23   
  */


#include <Wire.h>
//#include <PCF8574.h>
#include <I2CKeyPad.h> 
#include <LiquidCrystal_I2C.h> 
 
LiquidCrystal_I2C lcd(0x3F,20,4);

const uint8_t KEYPAD_ADDRESS = 0x20;
I2CKeyPad keyPad(KEYPAD_ADDRESS);
char keymap[19] = "123A456B789C*0#DNF";  // N = NoKey, F = Fail

unsigned char addr = 0x22;
//PCF8574 i2c_rly(addr);

#define RLY_1_on 0b11111110
#define RLY_2_on 0b11111101
#define RLY_3_on 0b11111011
#define RLY_4_on 0b11110111
#define RLY_5_on 0b11101111
#define RLY_6_on 0b11011111
#define RLY_7_on 0b10111111
#define RLY_8_on 0b01111111


/*
#define RLY_1_off 0b00000001
#define RLY_2_off 0b00000010    these don't work as expected
#define RLY_3_off 0b00000100    7/28/23
#define RLY_4_off 0b00001000
#define RLY_5_off 0b00010000
#define RLY_6_off 0b00100000
#define RLY_7_off 0b01000000
#define RLY_8_off 0b10000000
*/





///////////////////////////////////////////////////////////////

void setup() {

lcd.init();  
lcd.init();                 
 lcd.backlight();

  
 Wire.begin();
    Wire.setClock(400000);
    Wire.beginTransmission(addr);             
    Wire.write(0xFF);         // Turns off all relays
    Wire.endTransmission(); 

    keyPad.loadKeyMap(keymap);                         
  
            
                
 
}
 void i2c_relay(unsigned char addr, unsigned char value)
{
  Wire.beginTransmission(addr);             
  Wire.write(value);               
  Wire.endTransmission();  
  
}



//////////////////////////////////////////////////////////////////////

void loop()
{
   if (keyPad.isPressed())
  {
    char ch = keyPad.getChar();     // note we want the translated char
    int key = keyPad.getLastKey();
  
  // Light up key pressed on LCD
  switch (ch) {
    case '1':
      lcd.setCursor(0,0);
      lcd.print(ch);
      i2c_relay(addr, RLY_1_on);
        
    break;

   case '2':
      lcd.setCursor(3,0);
      lcd.print(ch);
       i2c_relay(addr, RLY_2_on);
    break;

    case '3':
      lcd.setCursor(6,0);
      lcd.print(ch);
        i2c_relay(addr, RLY_3_on);
    break;

    case '4':
      lcd.setCursor(0,1);
      lcd.print(ch);
        i2c_relay(addr, RLY_4_on);
    break;

    case '5':
      lcd.setCursor(3,1);
      lcd.print(ch);
        i2c_relay(addr, RLY_5_on);
    break;

    case '6':
     lcd.setCursor(6,1);
      lcd.print(ch);
        i2c_relay(addr, RLY_6_on);
    break;

    case '7':
      lcd.setCursor(0,2);
      lcd.print(ch);
      i2c_relay(addr, RLY_7_on);
    break;

    case '8':
      lcd.setCursor(3,2);
     lcd.print(ch);
        i2c_relay(addr, RLY_8_on);
    break;

  /*  case 'A':
      lcd.setCursor(12,0);
      lcd.print(ch);
    break;
    */
     case 'B':
      lcd.setCursor(8,2);
      lcd.print(ch);
      i2c_relay(addr,0b11111111);  
      lcd.print(" All Off");
     break;

   /* case 'C':
      lcd.setCursor(10,2);
      lcd.print(ch);
    break;
*/
    case 'D':
      lcd.setCursor(8,3);
      lcd.print(ch); 
      lcd.print(" clear LCD");     
      delay(1000);

      lcd.clear();    //lcd.clear();
    break;
        }
  }
}

As I have cobbled and pasted to accomplish the following.
I am using an external 5VDC to the Rely module (Ox22). So what I can do is hit a number button 1-8, (4x4 membrane keypad connected to PCF8574 module at 0x20)and that number appears on a 20x04 LCD (0x3F) while that relay is turned on and stays on until the next number is pressed. It turns off the last relay engaged and turns on the one for the new keypress.

I know there is a different way of coding other than the Switch() Case() routine to be able to turn on a relay and have it stay energized while I turn on other relays attached to solenoids so I can run the DC motors all the time and yet turn on/off the relays for the solenoids accordingly.

I will also add another PCF8574 (8-chanel) expansion module to be able to connect it, using a different address, so I can view the activity of the flag sensors as a piece of paper travels throughout the machine with the motors and clutches engaged, until the contents (just 2 pieces) is placed into an envelope and run over the moistening flap, reversed direct to close the flap and send the closed envelope into a storage bin.

Back to my dilemma, I'm lost as far as how to have the 1-8 number on the LCD via the I2C 4x4 keypad while that relay stays energized and I can engage other relays at the same time.
Any and all help is appreciated. FYI the schematics are not included because it doesn't matter, what I have hooked up works fine.

I had forwarded the wrong sketch. this is the one that works on a 1-relay-at-a-time with each button press.

How will helpers then get an overview? Nobel price novells don't do the job.

Is it a touch sensitive LCD?

Please read and use this topic: How to get the best out of this forum - Using Arduino / Project Guidance - Arduino Forum

1 Like

Since it works fine I will not look for the schematics that you did not draw and consider your problem solved!

If you want to keep multiple relays on/off, you need to keep track of the data byte you are writing to the PCF8574 and then toggle each bit and then write the byte out. Something like this:

  1. receive a '1' so toggle bit 0 of your data byte & write it out (assume data byte starts as 0x00 so now it is 0x01)
  2. receive a '2' so toggle bit 1 of your data byte & write it out (now your data byte is 0x03)
  3. receive a '1' so toggle bit 0 (0x02)

To achieve this, look at the docs for bitRead(), bitSet(), bitClear()

1 Like

blh64,
Thank you for seeing the big picture of my question. Also, thank you for the insights, which is what I was needing.

Regardless of a schematic, I have yet to see a schematic/sketch for an I2CLCD, I2C_Keypad and I2C 8-ch relay board all in one.

As far as a character I2C LCD, why have an I2C Keypad if it was a touch screen, or am I missing the part of the touch screen code/library that is not listed in my code? Also, the time it takes to convert a picture into a schematic leaves me little time to continue on to the bigger and better parts of my project, which is also explained in the "Nobel prize novels" section. Or should I have included more spacing to break things up more?

Of course it works fine. Yet, I cannot take it to the next level , independent operation of the relays included in a switch/case methodology. I need a way to switch each relay on via I2C keypad, displayed on a character I2C LCD, and have it stay on until I somehow tell it to turn off.

I understand that but there are thousands of ways of doing this, all dependent on how everything is connected. I cannot see what you can you need to tell me, the best way is in the language of electronics schematic. You have spent over a week to avoid doing a simple; schematic of your project that will take maybe 1 hour and get answers that will work. I believe you do not know how to draw a schematic. If you need a CAD (Computer Aided Design) program you can download KiCad and use it for free.

1 Like

Good luck!

Since your key codes '1' - '8' correspond to bit 0..7 of your control byte, you can reduce your switch statement down to computing what to do.

byte bitPosition;
byte dataByte;
...
switch (key) {
  case '1'...'8' :
    bitPosition = key - '1';  // now a number 0..7
    lcd.setCursor(0, bitPosition);
    if ( bitRead( dataByte ) == 1 ) {
      // relay was on so toggle off
      bitClear( dataByte, bitPosition);
      lcd.print(' ');
    }
    else {
      // relay was off so toggle on
      bitSet( dataByte, bitPosition);
      lcd.print(key);
    }

Edit: You will also need to write out your dataByte after adjusting the value in your switch statement

Your configuration is different from every other configuration. Assuming it is not different creates issues like the one you are experiencing. Hand-drawn diagrams are a great help. Start with a square for the MCU, put legs on the pins you will use, add device boxes near the legs, then indicate pins and devices.

Class 1 of Semester 1 of Year 1 "engineers" take mechanical drawing. How did you skip that? It was the most fun class.

I like it! That is the answer to my question.

I have to play with this a while.
Thanks again!

My_I2C_LCD_kypd_8-ch_rly_bd_schem.pdf (1.7 MB)
I know "nobody" likes Fritzing, yet I find it very fast for quick schematics. Besides, all you have to do is hit File>export>Image>PDF and ta da, you have a schematic that you can zoom in to see what's what.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.