I2C ByVac Keypad +Arduino

Cant get my new ByVac 4506 Keypads running =/, could someone please help?

Board:
Arduino Mega 2560

Mega I2C connection
Clockline = 21 (with pullup)
Dataline = 20 (with pullup)

Product:
http://www.byvac.com/bv3/index.php?route=product/product&product_id=73

Author (andrew1056) original tread
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1254607411

Library and examplecode:

#include <Wire.h> // i2c
#include <ByVacKeypad.h> // library for byvac i2c keypad


// default is 0x62 which is 8 bits, 0x31 is 7 bit address
ByVacKeypad keypad = ByVacKeypad(0x31);

void setup() {
  keypad.init();  // initialize the keypad. just clears buffer
  Serial.begin(9600);
}

void loop(){

  Serial.print("Keys in Buffer: ");
  int numkeys;
  Serial.print(numkeys);

  delay(2000);

  if(keypad.numkeys() > 0){
    Serial.print("Key Pushed: ");
    int getkey = keypad.getkey();
    Serial.print(getkey);
  }

  delay(2000);

  if(keypad.numkeys() > 0){
    Serial.print("Key Down: ");
    int keydown = keypad.keydown(); 
    Serial.print(keydown);
    // will return 1 if key is down and 0 otherwise
  }

}

I think it is written for the ByVac 4218, but hoped they where the same.

I've never used the part but a quick read of the datasheet shows the use of Repeated Starts. The default Wire library does not support the repeated start, so you may want to find out if the repeated start is a necessity or just a recommendation.

Can you give your exact wiring please? Pull-up sizes, and I presume you are connecting ground and 5V but just want to check.

Sorry for the late reply... been quite busy.

The library you're using was written for that I2C keypad. I haven't used a mega so I can't know if it's hooked up correctly, but there are a couple things:

The first was that I think his keypad memory mappings were wrong. There should be a sketch on my library download page that is for re-programming the eeprom values with correct ones.

To trouble shoot just run the sketch you posted and see if you get anything back. If nothing comes back you may want to use an I2C address finder sketch (don't remember what it's called exactly). You load it onto your arduino and it will print out the addresses of connected I2C devices. If you don't want to do that look in the datasheet for the factory reset. I don't remember how to do it, but the datasheet tells you how.

Hopefully this will help you get up and running, but if not I'll do my best to help you get it working.

Sorry for the late response as well, seems like the notify function didn't reach me.

I've got some help from a friend and did get it running without any libraries! But, I do have some problems

At startup it runs perfectly displaying some keys pressed, then suddenly flipps and output a number of random "keys" in a haste.
After that it works perfectly again for some keystrokes. I've been careful to check if the keypad is busy before requesting communication and also been careful to end transmission afterwards.

I2C is new to me so I bet the mistake is mine :smiley:

//ByVac Keypad 

#include <Wire.h> // I2C 

boolean SDA = 20; // I2C - serial data pin
boolean SCL = 21; // I2C - serial clock pin

int key = 255; //Starting value

void setup() {
  
  pinMode(SDA, INPUT);
  pinMode(SCL, INPUT);
  
  digitalWrite(SDA, HIGH);
  digitalWrite(SCL, HIGH);
  
  Wire.begin(); // join i2c bus
  
   // initialize the serial communication:
  Serial.begin(9600);
  Serial.println("initialization done");
  
}


void Getkey()   
{

if (digitalRead(SCL) == HIGH){    //Check if keypad is busy, LOW = busy, HIGH = good to go

key = 255;                         //Reset value "key"
  Wire.beginTransmission(0x31);    //Keypad Adress 
  Wire.send(4);                    //Getkey-function in keypad 
  Wire.endTransmission();         
  delayMicroseconds(45);           //Let keypad think for 45us
  Wire.beginTransmission(0x31);    //Reastablish comunication
  Wire.requestFrom(int(0x31), 1);  //Request one bit at keypad adress

  if (Wire.available()) {          //Value avalible?
    key = Wire.receive();          //Get value into "key"  
 }

Wire.endTransmission();            //End transmission
}
}



void loop() { //main loop
  
  Getkey();           //run function "Getkey"
 if(key != 255)       //If value has changed (key pressed and stored) serialprint it
 {

  digitalWrite(13, HIGH);
    
Serial.print("key ");
Serial.println(key);  

  digitalWrite(13, LOW);
}
}

Huh?

  pinMode(SDA, INPUT);
  pinMode(SCL, INPUT);
  
  digitalWrite(SDA, HIGH);
  digitalWrite(SCL, HIGH);

You don't need to do that, Wire.begin() does it.

And this?

boolean SDA = 20; // I2C - serial data pin
boolean SCL = 21; // I2C - serial clock pin

Booleans are true or false, you don't stuff numbers into them. And in any case, each chip has dedicated I2C lines, you don't need to tell the Wire library which ones to use.

Your code doesn't look anything like the example on the page you linked to. I'll reproduce it here because it was pretty unreadable:

#include <Wire.h> // i2c
#include <byvackeypad.h> // library for byvac i2c keypad

// default is 0x62 which is 8 bits, 0x31 is 7 bit address
ByVacKeypad keypad = ByVacKeypad(0x31);

void setup() {
  keypad.init();  // initialize the keypad. just clears buffer
  Serial.begin(9600);
}

void loop(){

  Serial.print("Keys in Buffer: ");
  int numkeys;
  Serial.print(numkeys);

  delay(2000);

  if(keypad.numkeys() < 0){
    Serial.print("Key Pushed: ");
    int getkey = keypad.getkey();
    Serial.print(getkey);
  }

  delay(2000);

  if(keypad.numkeys() < 0){
    Serial.print("Key Down: ");
    int keydown = keypad.keydown(); 
    Serial.print(keydown);
    // will return 1 if key is down and 0 otherwise
  }

}

Even if you don't use his library, you don't check the SCL line to see if the "device is busy".

Instead of this:

void Getkey()   
{

if (digitalRead(SCL) == HIGH){    //Check if keypad is busy, LOW = busy, HIGH = good to go

key = 255;                         //Reset value "key"
  Wire.beginTransmission(0x31);    //Keypad Adress 
  Wire.send(4);                    //Getkey-function in keypad 
  Wire.endTransmission();         
  delayMicroseconds(45);           //Let keypad think for 45us
  Wire.beginTransmission(0x31);    //Reastablish comunication
  Wire.requestFrom(int(0x31), 1);  //Request one bit at keypad adress

  if (Wire.available()) {          //Value avalible?
    key = Wire.receive();          //Get value into "key"  
 }

Wire.endTransmission();            //End transmission
}
}

It would be much more like this (untested):

//ByVac Keypad 

#include <Wire.h> // I2C 

#define DEVICE_ADDRESS 0x31

void setup() {
  
  Wire.begin(); // join I2C bus as master

  // initialize the serial communication:
  Serial.begin(9600);
  Serial.println("initialization done");

}


byte Getkey()   
{
  Wire.beginTransmission(DEVICE_ADDRESS);    //Keypad Adress 
  Wire.send(4);                    //Getkey-function in keypad 
  Wire.endTransmission();     

  Wire.requestFrom(DEVICE_ADDRESS, 1);  //Request one byte from keypad

  if (Wire.available())          //Value avalible?
    return Wire.receive();          //Get value into "key"  

  return 0xFF;  // no response
}



void loop() { //main loop

  byte key = Getkey();           //run function "Getkey"
  
  if(key != 0xFF)       //If value has changed (key pressed and stored) serialprint it
  {

    digitalWrite(13, HIGH);

    Serial.print("key ");
    Serial.println(key, DEC);  

    digitalWrite(13, LOW);
  }
}

This is a simple device that should not be very hard to get going. There is a library for it here:
http://doc.byvac.com/index.php5?title=Arduino_BV4606

This code when using the library will reflect key presses to the serial monitor:

#include <bv4506.h>
#include <I2c_bv.h>
#include <Wire.h>

// 7 bit adddress is used
BV4506 keypad(0x21); // changed from 0x62 to 0x42

// serial used for output
void setup()
{
Serial.begin(9600);
Wire.begin();
Serial.print("\nStarted\n");
}

void loop()
{
keypad.clear();
while(1) {
if(keypad.keys())
Serial.println(keypad.key());
delay(200); // dont hog I2C bus
}
}