Problems with 4x4 keypad virtualwire ssprintfand sscanf

Hi all

Could you please help me with the issue I am having with my code.

I am having an issue with sprintf and sscanf on the transmit and/or receive side of my link.
Without these two my kepresses transmitted work fine
Once I enable the use of sprintf and sscanf the keypress number becomes 609 and none of the

variables fill up correctly on the remote side.
I have been sitting up until the early hours of the morning for weeks and have learned so much

with this hobby project now and I am finally at wits end and think I need a little nudge so I can

continue on.

I would really appreciate and help guidance solutions and comments.

Den

Please find the pseudo code here.

Psuedo code

At the transmitter :

Enter code or codes via keypad which accepts multiple keypresses (some are pre-populated currently

untill the keypad menu is complete) these codes are visible and should be visible on LCD and

serial monitor.

Codes variables are:
hcode (Should hold 4 or less characters - pre-populated for now)
devcode (fetched from keypad - (type in 123#) currently set to 4 characters but could/would like

to be changed in future.)
pcode (2 characters alphanumeric W7 Pre-populated for now)
oocode (3 or less digits)

allcode (should holds all codes for sending and either wirelessly or via serial)

Currently using :
4x4 matrix keypad (working)
virtual wire (working)
Passing the variables (not working)
At the receiver:

Receive code (allcode)
Parse allcode and split individual codes namely:
hcode
devcode
pcode
oocode
Codes would be displaed on serial monitor and/or LCD
Use If or Switch case statement to perform action based on codes
(was working ..currently commented out/disabled)

Here's the code I have so far.
I have entered a lot of serial.print for debugging

The transmitter

// include the library code:
//#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
//LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

//include virtual wire library
#include <VirtualWire.h>

//include keypad library
#include <Keypad.h>

//declare the format of the VARIABLES and the VARIABLES
char key; //holds single key
char buffer[4]; //holds keys pressed
int i; //counter
//declare "code-holding" vars
char hcode;
char devcode [4];
char pcode;
char oocode;
char allcode[13];

/*
keypad map
*/

const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {8, 9, 10, 13}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {A0, A2, A1, A3}; //connect to the column pinouts of the keypad

   Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup(){

// Initialise the IO and ISR --radio
   vw_setup(2000);       // Bits per sec
   vw_set_tx_pin(7);

//Serial Section
  Serial.begin(9600);

  /* 
  //LCD Section
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 4);
  //Print a message to the LCD.
  lcd.print("hello, world!");
  lcd.clear();
  delay(1000);
  */
}
  
void loop(){
  i = 0;
  buffer[0] = '\0'; //NULL the array
  while( i < sizeof(buffer)) // removed this last one - 1)
  {
    
  key = keypad.getKey();
  if (key == '#')
     {
       Serial.print("Sent");
       Serial.write(buffer[i]);
       lcd.print("Sent");
       delay(1000);
       lcd.clear();
       devcode[i] = atoi((char*) buffer);
       devcode[i]= buffer[i];
       hcode=45;
       pcode=1;
       oocode=1;
     
     //for debugging  
        Serial.println();
       Serial.print("this is buffer[i]");
       Serial.write(buffer[i]);
        Serial.println();
       Serial.print("This is devcode[i]");
       Serial.write(devcode);
        Serial.println();
        
       Serial.print("This is hcode ");
       Serial.write(hcode);
        Serial.println();
       Serial.print("This is pcode ");
       Serial.write(pcode);
        Serial.println();
       Serial.print("This is oocode ");
       Serial.write(oocode);
        Serial.println();
       Serial.print("This is buffer ");
       Serial.write(buffer);
        Serial.println();
       Serial.print("This is devcode ");
       Serial.write(devcode);
        Serial.println();

   //prepare the message and format the message as allcode       
       sprintf(allcode, "%d,%d,%d,%d", hcode, oocode, pcode, devcode);
   //send it     
       vw_send((uint8_t *)allcode, strlen(allcode));
       
       //for debugging
       Serial.print("This is allcode ");
       Serial.print(allcode);
        Serial.println();
        
       //vw_send((uint8_t *)buffer,8);
       
       vw_wait_tx(); // Wait until the whole message is gone

    break;
     }
   
    
   else if ( key != NO_KEY) //if(key)  is (or is it the same as) if(key != NO_KEY)
    {
      //Serial.print("This is key ");
      //Serial.print(key);
      lcd.print(key);
      buffer[i] = key;
      i++;
      buffer[i]= '\0';
      }
   
  }
  //Serial.print("Sending       "); 
  Serial.print(buffer);
  
}
 
   
   /* left around for testing
   char getChar()
{
  char key = keypad.getKey();
  if (key != NO_KEY)
  {
     return key;
  }
  else { 
  return NO_KEY;
   }
  }
*/

The receiver

/*Using 
SimpleReceive
  This sketch  displays text strings received using VirtualWire
  Connect the Receiver data pin to Arduino pin 11
*/
#include <VirtualWire.h>

byte message[VW_MAX_MESSAGE_LEN];    // a buffer to hold the incoming messages
byte msgLength = VW_MAX_MESSAGE_LEN; // the size of the message
int code;
byte allcode; //should hold all codes
int hcode; // 4 digit code (can it containd alpha numerics ABCD?)
int devcode; //4 digits or lesss - exactly what you enter on keypad
int pcode; //a two digit code - could contain aplpha numerics eg A1
int oocode; // up to 3 digits - numbers only 0 to 255


// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;

void setup()
{
  
    Serial.begin(9600);
    Serial.println("Ready"); //for debugging

    // Initialize the IO and ISR
    vw_setup(2000);             // Bits per sec
    vw_rx_start();              // Start the receiver
      vw_set_rx_pin(3);         //receive pin set to 3
     // initialize the digital pin as an output.
  pinMode(led, OUTPUT); // set led pin 13 as output
}

void loop()
{
    if (vw_get_message(message, &msgLength)) // Non-blocking
    {
        Serial.print("Got: "); //for debugging 
    for (int i = 0; i < msgLength; i++) //counter loop for received message length
    {
      allcode = atoi((char*) message);
      //allcode=message;
      //sscanf((char*)allcode, "%s,%s,%s,%s",&hcode,&oocode,&pcode,&devcode); // Converts a string to an array
      //wasnt working with allcode variable so pointed sscanf to message to break it down
      sscanf((char*)message, "%s,%s,%s,%s",&hcode,&oocode,&pcode,&devcode); // Converts a string to an array
        
        // added this to convert message charcters to an int
		code = atoi((char*) message);

     //for debugging
    //Serial.print("this is message inside loop");
    Serial.print("this is message[i] in loop ");
		Serial.write(message[i]);
     Serial.println();

    Serial.print("this is inside loop code value ");
    Serial.write(code);
     Serial.println();
    Serial.print("this is allcode ");
    Serial.write(allcode);
     Serial.println();
    //Serial.print("this is allcode[i] ");
    //Serial.write(allcode[i]);
    }
     Serial.println();
    
    Serial.print("this is outside of loop ");
     Serial.println();
    Serial.print("this is code ");
    Serial.write(code);
     Serial.println();
   
 //  for debugging
    Serial.print("this is hcode");
    Serial.write(hcode);
     Serial.println();
    Serial.print("this is devcode");
    Serial.write(devcode);
     Serial.println();
    Serial.print("this is pcode");
    Serial.write(pcode);
     Serial.println();
    Serial.print("this is oocode");
    Serial.write(oocode);

//for eventual code matching   
//code matching
//if (code == 145)
//{
//  Serial.print("code MATCH!!");
//   digitalWrite(13, !digitalRead(13));  // toggle pin state
  //digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
//}
  
//null the arrays
    hcode= '\0';
    devcode= '\0';
    pcode= '\0';
    oocode= '\0';
    allcode='\0';
   code= '\0'; 
   //possible code below to clear array - had issues
   //memset( allcode, 0, sizeof( allcode));// This line is for reset the allcode
    
    }
}
   else if ( key != NO_KEY) //if(key)  is (or is it the same as) if(key != NO_KEY)
    {
      //Serial.print("This is key ");
      //Serial.print(key);
      lcd.print(key);
      buffer[i] = key;
      i++;
      buffer[i]= '\0';
      }

Doesn't it matter whether there is room in the buffer?

  while( i < sizeof(buffer)) // removed this last one - 1)
  {

i can go to 3, which results in you writing beyond the end of the array in the above code.

Only YOU can see what keys you pressed. Only you can see your serial output.

       devcode[i] = atoi((char*) buffer);
       devcode[i]= buffer[i];

Why bother calling atoi()?

       Serial.print("This is devcode[i]");
       Serial.write(devcode);

No, it isn't.

Codes variables are:
hcode (Should hold 4 or less characters - pre-populated for now)
devcode (fetched from keypad - (type in 123#) currently set to 4 characters but could/would like

to be changed in future.)
pcode (2 characters alphanumeric W7 Pre-populated for now)
oocode (3 or less digits)

13 characters and a NULL do not fit in a 13 element array.

      //allcode=message;

Is your delete key broken? Code that no longer makes sense needs to be deleted, not commented out.

      sscanf((char*)message, "%s,%s,%s,%s",&hcode,&oocode,&pcode,&devcode); // Converts a string to an array

No, it doesn't. hcode, oocode, pcode, and devcode are NOT strings. The %s format specifier is incorrect.

Hi

PaulS

Thanks for the reply..see below for mine:

else if ( key != NO_KEY) //if(key)  is (or is it the same as) if(key != NO_KEY)
    {
      //Serial.print("This is key ");
      //Serial.print(key);
      lcd.print(key);
      buffer[i] = key;
      i++;
      buffer[i]= '\0';
      }

Doesn't it matter whether there is room in the buffer?

It didn't seem to make a difference regarding the buffer size when only keypad and virtual wire were working together, in fact since several keys may be typed in until a # is entered the buffer size is dynamic.

are you referring to the buffer declarations on the transmitter side ?

char buffer[4]; //holds keys pressed
int i; //counter

If so then 3 keypresses + 1 for null buffer = 4
I set it to 5 (4 keypresses + null buffer)
Is this correct ?
This then would affect the following setting not so ?

while( i < sizeof(buffer)) // removed this last one - 1)
  {
[quote]i can go to 3, which results in you writing beyond the end of the array in the above code[/quote].
So are you saying I should leave this as 
CODE
while( i < sizeof(buffer)) - 1)

If so then If I want to catch and fill the buffer with 4 keypresses the number should be 6 for

char buffer[6]

Is that right ?

I'm not quite sure what you're saying here :

Only YOU can see what keys you pressed. Only you can see your serial output.

devcode[i] = atoi((char*) buffer);
       devcode[i]= buffer[i];

Why bother calling atoi()?

The atoi was used as a test..
I didn't see it was still there ..will check it thanks a million :slight_smile:

Serial.print("This is devcode[i]");
       Serial.write(devcode);

No, it isn't.

What is it ?

Yes you're quite right on this one :

Codes variables are:
hcode (Should hold 4 or less characters - pre-populated for now)
devcode (fetched from keypad - (type in 123#) currently set to 4 characters but could/would like

to be changed in future.)
pcode (2 characters alphanumeric W7 Pre-populated for now)
oocode (3 or less digits)

13 characters and a NULL do not fit in a 13 element array.

Are you suggesting I change it to 14 ? (13+1)

char allcode[14]

Should I hold the variables as characters or strings or convert the allcode array to a string before sending ?
Should I declare all code variables as arrays and add add an extra element in to hold the NULL character ?

//allcode=message;

Is your delete key broken? Code that no longer makes sense needs to be deleted, not commented out.

IsthathumourMydeletekeyisworkingperfectlyMindisonmalfunctionandnowitseemsmyspacebarisnotfucntioning
Damnifonlyiknewthatremarksincodeareusedfordescriptionsandcommentsandsometimesasatemporarymethodtohold
codewithoutdeletingitThisoftensavesonehavingtoretypecodewhenyouneedtobringitbacknotso?

sscanf((char*)message, "%s,%s,%s,%s",&hcode,&oocode,&pcode,&devcode); // Converts a string to an array

No, it doesn't. hcode, oocode, pcode, and devcode are NOT strings. The %s format specifier is incorrect

.

Yes human error again..I tried %d as well as a %c and numerous other options with the command
I left it as %s for examination here since all the other options weren't helping.
So If NOT STRING then are the all char's?

PaulS
I will go back and check and/or change all the spots you identified and document the results.
Any other comments help and tips would be greatly appreciated.

On a side note:
Should I rather use the STRTOK function to combine the contents of all the char variables into a single array ?

Kind regards

Den

It didn't seem to make a difference regarding the buffer size when only keypad and virtual wire were working together, in fact since several keys may be typed in until a # is entered the buffer size is dynamic.

No, it isn't:

char buffer[4]; //holds keys pressed

That's a static buffer.

The while loop iterates while i is 0, 1, 2, and 3. On each iteration, you store a key value in one position in the array and a NULL in the next position (0 and 1, 1 and 2, 2 and 3, 3 and 4). Storing the NULL in [4] is wrong, since [4] is out of bounds of the array.

I'm not quite sure what you're saying here :

I'll try again, then. My crystl ball is broken. I can't see what you are typing. I can't see what appears in the serial monitor on your computer. If you share those important bits of information, we are more likely to be able to help you.

What is it ?

You are printing the whole array, not the ith element of the array.

Are you suggesting I change it to 14 ? (13+1)

Yes (or more). I'd be inclined to keep the size a multiple of 2, so I'd use 16.

IsthathumourMydeletekeyisworkingperfectlyMindisonmalfunctionandnowitseemsmyspacebarisnotfucntioning
Damnifonlyiknewthatremarksincodeareusedfordescriptionsandcommentsandsometimesasatemporarymethodtohold
codewithoutdeletingitThisoftensavesonehavingtoretypecodewhenyouneedtobringitbacknotso?

You are asked to post the minimum code that illustrates a problem. Commented out code is NOT part of the problem. Wading through lots of code everyday, trying to pick out the relevant bits is tiring. Make it easier by deleting stuff that you no longer need.

You can make backup copies. Just don't post them.

So If NOT STRING then are the all char's?

No, they are all ints. You need to concentrate on debugging one side at a time. Until the sender is sending good data, parsing it doesn't make sense. When the sender is sending good data, then you can focus on parsing it. Parsing data that keeps changing is impossible. Don't even try, until the data is stable.

Should I rather use the STRTOK function to combine the contents of all the char variables into a single array ?

No. The strtok() function is for separating delimiter separated data into useful tokens, which is the opposite of what the sender needs to do.

Hi again

PaulS ...thanks a million for the reply. It sent me hurtling back to re-check the code.

I noticed by trial and error that the array was sized way too small for char's so I bumped up the number and presto it showed up on the serial monitor.
See the attached serial monitor snippet for crystal ball reference :slight_smile:

I now have it working fairly well and almost ready to send to the receiver which I will debug next but first there a few issues:
sadly I havent figured out how to post a pic in this reply screen

  1. I would like the char buffer[] array (which holds the keypresses which are entered via 4x4 matrix keypad using a # key)
    to equal another array called 'devcode'.
    The devcode array always is blank or un-populated..I think it used t show the value 609
    How do I make it equal to/have the same content as buffer ? This intern will also be sent along with buffer[]
    If I place buffer into the ssprintf command then buffer's value gets loaded into the ssprintf result.
  2. Are there any optimizations you recommend I make or change ?

Here is the code :

// include the library code:
//#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
//LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

//include virtual wire library
#include <VirtualWire.h>

//include keypad library
#include <Keypad.h>

//declare the format of the VARIABLES and the VARIABLES
char key; //holds single key
char buffer[4]; //holds keys pressed
int i; //counter
//declare "code-holding" vars
char hcode[5] = {"1234"}; //5 digits/keys eg 123 + NULL
char devcode[4]; //4 digits/keys eg 123 + NULL 
char pcode[3] = {"21"}; //2 digits/keys eg 123 + NULL
char oocode[4] = {"234"}; //3 digits/keys eg 123 + NULL
char allcode[200]; //total array count including NULL's

/*
keypad map
*/

const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {8, 9, 10, 13}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {A0, A2, A1, A3}; //connect to the column pinouts of the keypad

   Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup(){

// Initialise the IO and ISR --radio
   vw_setup(2000);       // Bits per sec
   vw_set_tx_pin(7);

//Serial Section
  Serial.begin(9600);

  /* 
  //LCD Section
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 4);
  //Print a message to the LCD.
  lcd.print("hello, world!");
  lcd.clear();
  delay(1000);
  */
  
  //NULL the arrays
   buffer[0] = '\0'; //NULL the array
   //devcode[0] = '\0'; //NULL the array
   //pcode[0] = '\0'; //NULL the array
   //oocode[0] = '\0'; //NULL the array
   //allcode[0] = '\0'; //NULL the array
}
  
void loop(){
  i = 0;
  buffer[0] = '\0'; //NULL the array
  while( i < sizeof(buffer)) // removed this last one - 1)
  {
    
  key = keypad.getKey();
  if (key == '#')
     {
       Serial.print("Sent");
       Serial.write(buffer[i]);
       //lcd.print("Sent");
       delay(1000);
       //lcd.clear();
       

      devcode[i] = atoi((char*) buffer);
       devcode[i]= buffer[i];
            
     //for debugging  
        Serial.println();
       Serial.print("this is buffer[i]");
       Serial.write(buffer[i]);
        Serial.println();
       Serial.print("This is devcode[i]");
       Serial.write(devcode);
        Serial.println();
        //print array devcode for testing
        int x;
for (x = 0; x < 5; x = x + 1) {
  Serial.println(devcode[x]);
}
        //end of print array
       Serial.print("This is hcode ");
       Serial.write(hcode);
        Serial.println();
       Serial.print("This is pcode ");
       Serial.write(pcode);
        Serial.println();
       Serial.print("This is oocode ");
       Serial.write(oocode);
        Serial.println();
       Serial.print("This is buffer ");
       Serial.write(buffer);
        Serial.println();
       Serial.print("This is devcode ");
       Serial.write(devcode);
        Serial.println();

   //prepare the message and format the message as allcode       
       sprintf(allcode, "%s,%s,%s,%s,%s,%s", buffer, hcode, pcode, oocode, devcode, allcode);
   //send it     
       vw_send((uint8_t *)allcode, strlen(allcode));
             
              //for debugging
       Serial.print("This is allcode ");
       Serial.print(allcode);
       Serial.println();
        
       //vw_send((uint8_t *)buffer,8); //for debugging
       
       vw_wait_tx(); // Wait until the whole message is gone
       
       buffer[0] = '\0'; //NULL the array
       //devcode[0] = '\0'; //NULL the array
       //pcode[0] = '\0'; //NULL the array
       //oocode[0] = '\0'; //NULL the array
       allcode[0] = '\0'; //NULL the array
    break;
     }
         
   else if ( key != NO_KEY) //if(key)  is (or is it the same as) if(key != NO_KEY)
    {
      //Serial.print("This is key ");
      //Serial.print(key);
      //lcd.print(key);
      buffer[i] = key;
      i++;
      buffer[i]= '\0';
      }
       
  }
  //Serial.print("Sending       "); 
  Serial.print(buffer);
  
}
 
   
   /* left around for testing
   char getChar()
{
  char key = keypad.getKey();
  if (key != NO_KEY)
  {
     return key;
  }
  else { 
  return NO_KEY;
   }
  }
*/

Kind regards

Den

How do I make it equal to/have the same content as buffer ?

memcpy(), strcpy() or your own for loop.

  1. Are there any optimizations you recommend I make or change ?

allcode is WAY too big.

  //NULL the arrays
   buffer[0] = '\0'; //NULL the array
   //devcode[0] = '\0'; //NULL the array
   //pcode[0] = '\0'; //NULL the array
   //oocode[0] = '\0'; //NULL the array
   //allcode[0] = '\0'; //NULL the array

The arrays already contain nothing but NULLs.

  while( i < sizeof(buffer)) // removed this last one - 1)
  {

This loop still iterates from 0 to 3.

      buffer[i] = key;
      i++;
      buffer[i]= '\0';

It STILL writes into positions 0, 1, 2, 3, and 4 of the 4 element array.

      devcode[i] = atoi((char*) buffer);
       devcode[i]= buffer[i];

It still uselessly calls atoi().

Hi all

Could somebody please help me out with my code.

I have been at this for nearly two months now and have learned so much already but I am battling here and would really appreciate a little help so I can continue on and also understand where I keep going wrong.

With reference to the picture of serial terminal output and to my code below.


Heres the transmitter code:

#include <VirtualWire.h>
#include <Keypad.h>
#include <string.h>
char key; //holds single key
char buffer[4]; //holds keys pressed
int i; //counter
//declare "code-holding" vars
char hcode[5] = {"1234"}; //5 digits/keys eg 123 + NULL
char devcode[5]; //4 digits/keys eg 123 + NULL 
char pcode[3] = {"21"}; //2 digits/keys eg 123 + NULL
char oocode[4] = {"234"}; //3 digits/keys eg 123 + NULL
char allcode[18]; //total array count including NULL's

const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {8, 9, 10, 13}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {A0, A2, A1, A3}; //connect to the column pinouts of the keypad

   Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );



void setup(){

// Initialise the IO and ISR --radio
   vw_setup(2000);       // Bits per sec
   vw_set_tx_pin(7);
  Serial.begin(9600);
 
  //NULL the arrays I have nulled these to chek if there was any change and to show I have used them.Please advise
 // as to which to use or not use.

   buffer[0] = '\0'; //NULL the array
   //devcode[0] = '\0'; //NULL the array
   //pcode[0] = '\0'; //NULL the array
   //oocode[0] = '\0'; //NULL the array
   //allcode[0] = '\0'; //NULL the array
}
  
void loop(){
  i = 0;
  buffer[0] = '\0'; //NULL the array
  while( i < sizeof(buffer)) // removed this last one - 1)
  {
  
    key = keypad.getKey();
  if (key == '#')
     {
       Serial.print("Sent allcode = hcode, pcode, oocode, devcode");
     memcpy(devcode, buffer, sizeof(buffer));      
      
showme();

   //prepare the message and format the message as allcode       
       sprintf(allcode, "%s,%s,%s,%s", hcode, pcode, oocode, devcode);
   //send it     
       vw_send((uint8_t *)allcode, strlen(allcode));
      Serial.print("This is allcode ");
       Serial.print(allcode);
       Serial.println();
       
       vw_wait_tx(); // Wait until the whole message is gone
                   
       buffer[0] = '\0'; //NULL the array
       memset( devcode, 0, sizeof(devcode));// This line is to reset devcode
       memset( buffer, 0, sizeof(buffer));// This line is to reset buffer
       memset( allcode, 0, sizeof( allcode));// This line is to reset allcode
    break;
     }
         
   else if ( key != NO_KEY) //if(key)  is (or is it the same as) if(key != NO_KEY)
    {
     buffer[i] = key;
      i++;
      buffer[i]= '\0';
      }
       
  }
  Serial.print(buffer);
  
}

void showme(){
    //for debugging  
        Serial.println();
       Serial.print("hcode :");
       Serial.write(hcode);
       Serial.println();
       Serial.print(",pcode :");
       Serial.write(pcode);
       Serial.println();
       Serial.print(",oocode :");
       Serial.write(oocode);
       Serial.println();
       Serial.print(",devcode :");
       Serial.write(devcode);
       Serial.println();
       Serial.print(",key buffer :");
       Serial.write(buffer);
        Serial.println();
        return;
}

The receiver code:

/*
  SimpleReceive
  This sketch  displays text strings received using VirtualWire
  Connect the Receiver data pin to Arduino pin 11
*/
#include <VirtualWire.h>

byte message[VW_MAX_MESSAGE_LEN];    // a buffer to hold the incoming messages
byte msgLength = VW_MAX_MESSAGE_LEN; // the size of the message
byte allcode[VW_MAX_MESSAGE_LEN]; //should hold all codes
char hcode[4]; // 4 digit code (can it containd alpha numerics ABCD?)
char devcode[4]; //4 digits or lesss - exactly what you enter on keypad
char pcode[2]; //a two digit code - could contain alpha numerics eg A1
char oocode[3]; // up to 3 digits - numbers only 0 to 255

void setup()
{
    Serial.begin(9600);
    Serial.println("Ready");

    // Initialize the IO and ISR
    vw_setup(2000);             // Bits per sec
    vw_rx_start();              // Start the receiver
      vw_set_rx_pin(3);
    
}

void loop()
{
    if (vw_get_message(message, &msgLength)) // Non-blocking
    {
        Serial.print("Got: ");
    for (int i = 0; i < msgLength; i++)
    {
        Serial.write(message[i]);
    }
    
    Serial.println();
    sscanf((char*)message, "%s,%s,%s,%s",&hcode,&pcode,&oocode,&devcode); // Converts a string to an array
    Serial.print("hcode: ");
    Serial.write(hcode);
     Serial.println();
    Serial.print("pcode: ");
    Serial.write(pcode);
     Serial.println();
    Serial.print("oocode: ");
    Serial.write(oocode);
     Serial.println();
    Serial.print("devcode: ");
    Serial.write(devcode);
     Serial.println();
  }
}

1.On the first keypad entered at the transmitter, the receiver gets the full set of what

was sent (allcode variable)
In this case the keycode entered was 5896 (4 digits)

2.On the next keypress 627 was entered (3 digits) at the transmitter side and the receiver

receives it too no problem.

3.The keypress entered is 123 (3 digits)
and the receiver still getting the correct message.

4.Here's where things go off the rails.
The keypress entered is 453 (3 digits)
But the receiver is now not showing the full received code at all :frowning:
Got:1234,21

I'm really at a loss.

To sum up all I would like to happen is the following.

1.A number is entered via keypress(devcode - 4 digits or less - this could includes
A,B,C,D for example 123A - but doesn't have to..could be digits only)
Once hash is pressed the entry is complete and the number is added to a string
using sscanf (hcode,pcode,oocode,devcode) to create a new variable
called allcode.
sscanf adds these together and separates them with commas (,)
This Seems to be working so far, although I could well have messed
up somewhere and would appreciate a little guidance or help here.
Being a newbie it's been rather long hours and late nights getting to this point.

2.Once the sscanf result allcode is obtained and created it gets sent
using virtualwire to the receiver.
This seems to work as well.
I have checked using the standard virtualwire receive example.
It all seemed fine with raw hex codes being received but then in an attempt to get this working I added this line in in order to sort the message into its separate variable/arrays.

sscanf((char*)message, "%s,%s,%s,%s",&hcode,&pcode,&oocode,&devcode); // Converts a string

I think this is where one of the problems is.

  1. The receiver receives allcode and then I would like to break it down into each of the variables namely hcode,pcode,oocode and devcode.

  2. Once thats done I would like to use a string compare or similar (==)
    to decide what o with each code.

Well that's it so far ..I really hope that someone can help me with this so I can move past this and learn more as I go because I just can't seem to see where the problem is.

Perhaps I have sized the arrays incorrectly or put things in the wrong places in the loops or messed up on the loop counts or pointers or conversions or something like the wrong conversion to char or string or int or putting the wrong counter variables in or referencing the wrong ones.

Thanking you in advance

Den

You have far to much going on in this bit of code, all without any real understanding of the different things you are trying to do So start again pick just one bit of the problem (it's called top down design). Create a new program which deals with just one thing get that working then get a simple program which deals with the next bit and so on.

After that you can start putting the bits together. At the moment you have just to much bad code to let anyone help you.

Mark

Your receiver has this code to parse the incoming message:

sscanf((char*)message, "%s,%s,%s,%s",&hcode,&pcode,&oocode,&devcode);

This seems to be intended to split your input line at the commas.

Later on it prints out this value for the input message:

Got: 1234,21,234,5896

Then it prints out this value for hcode:

hcode: 1234,21,234,58

Is that the correct value? It looks wrong to me. What scanf has done is return the address of the start of the string, but the string is not terminated at the end of that field so the field is not separated from the following fields. If you want to separate the fields, as I suspect you do, then strtok() might be a more appropriate way to achieve that. But wouldn't it be easier to design your solution so the message doesn't need to be reformatted at the receiver?

Hi all

Mark thanks for the top-down tip ... all of the individual pieces work. For example the keypress capturing of multiple keypresses.
The virutual wire works like a charm when sending bot combines and individual keystrokes no problem for example if you key in 5678# this gets sent and arrives at the receiver no problem.
My issues started when I wanted to combine the collected keypress and add more variables to it.,receive those and then split it up again This is where I am now having problems.

PeterH thanks for the reply.

You are 100% correct regarding the receiver side.. the receiver side seems to be where the problem lies.
As you say

Got: 1234,21,234,5896

Then it prints out this value for hcode:

Quote
hcode: 1234,21,234,58

The correct code at the receiver should be what was sent namely

1234,21,234,5896

Since 5896 was entered at the keypad at the transmitter.

If I type in a for digit number say 4567# this comes through fine.
If I type in a 3 digit number like 789# on the next send that comes through fine too.
But let's say I try another 4 digit on the next send, say 6547# the receiver side will show it as 654 .. chopping off the last digit or digits.
It seems almost like a full buffer or flooded array.

I would happily send a single string to the receiver which is why I chose sscanf which makes a single string.
The idea is that on the receiver side it will get chopped up into each unique field and then each field is matched for action/filtering. For example if devcode is 767 then activate sensor.
I definitely will explore the strtok() option.

What are you suggesting regarding this statement ?

But wouldn't it be easier to design your solution so the message doesn't need to be reformatted at the receiver?

I need each receiver to make its own decisions based on what it is sent. Each receiver will be autonomous and unique.

Den

IsthathumourMydeletekeyisworkingperfectlyMindisonmalfunctionandnowitseemsmyspacebarisnotfucntioning
Damnifonlyiknewthatremarksincodeareusedfordescriptionsandcommentsandsometimesasatemporarymethodtohold
codewithoutdeletingitThisoftensavesonehavingtoretypecodewhenyouneedtobringitbacknotso?

Ach, my eyes!

My issues started when I wanted to combine the collected keypress and add more variables to it.,receive those and then split it up again This is where I am now having problems.

Perhaps if you post your revised code?

Please use code tags.

Read this before posting a programming question

char hcode[5] = {"1234"}; //5 digits/keys eg 123 + NULL
char devcode[5]; //4 digits/keys eg 123 + NULL 
char pcode[3] = {"21"}; //2 digits/keys eg 123 + NULL
char oocode[4] = {"234"}; //3 digits/keys eg 123 + NULL
char hcode[4]; // 4 digit code (can it containd alpha numerics ABCD?)
char devcode[4]; //4 digits or lesss - exactly what you enter on keypad
char pcode[2]; //a two digit code - could contain alpha numerics eg A1
char oocode[3]; // up to 3 digits - numbers only 0 to 255

No matter how much you wish you could, you can not store the data in smaller arrays than were used to send it.

YOU MUST ALLOW ROOM FOR THE TERMINATING NULL. WE WILL NOT TELL YOU AGAIN!

Hi All

First of to thanks to all of you who have replied so far.

@Mark
The code actually only has 3 elements but it did get me off to thinking about each one and sifting through the elements again.
You said...

At the moment you have just to much bad code to let anyone help you.

Where did you see it ? And what did you consider bad code?
Every bit you find helps me understand and fix it.

@PeterH

What scanf has done is return the address of the start of the string, but the string is not terminated at the end of that field so the field is not separated from the following fields.

Which string ?

@Nick aka hawk-eyes

Revised code in this post :slight_smile:

I am doing my very best to stick to the forum rules regarding programming messages. Some interesting stuff there actually thanks to all of you who have contributed and keep it up, I think it's an amazing resource. Thank you!

@PaulS
Thanks a million for the continued replies.

From an earlier posting

No, it doesn't. hcode, oocode, pcode, and devcode are NOT strings. The %s format specifier is incorrect.

Which format specifier do you suggest.. I have tried %d , %s,%i
and these:
d or i Signed decimal integer 392
u Unsigned decimal integer 7235
o Unsigned octal 610
x Unsigned hexadecimal integer 7fa
X Unsigned hexadecimal integer (uppercase) 7FA
f Decimal floating point, lowercase 392.65
F Decimal floating point, uppercase 392.65
e Scientific notation (mantissa/exponent), lowercase 3.9265e+2
E Scientific notation (mantissa/exponent), uppercase 3.9265E+2
g Use the shortest representation: %e or %f 392.65
G Use the shortest representation: %E or %F 392.65
a Hexadecimal floating point, lowercase -0xc.90fep-2
A Hexadecimal floating point, uppercase -0XC.90FEP-2
c Character a
s String of characters sample
p Pointer address b8000000

No, they are all ints. You need to concentrate on debugging one side at a time. Until the sender is sending good data, parsing it doesn't make sense. When the sender is sending good data, then you can focus on parsing it. Parsing data that keeps changing is impossible. Don't even try, until the data is stable.

I have made the corrections to the array sizing as per your recommendations
How is it looking now ?

Ok, so far the transmitter and receiver side seem to be looking good in terms of the transmitted message getting through, I tested this by removing/commenting the sscanf line completely.

 Got: 
1234,21,234,5896

See the attached pic which as all send and received attempts marked in blue.

I am now battling with splitting the received message into arrays at the receiver side.
Please see the receiver code.
I have left a commented sscanf line in the code for reference.
I notice that when this is removed the data is received correctly. See the attached pic for the transmitted and received terminals.
So all that's left now is to split the received data into each individual array (the yellow part int the attached photo.) and that is what I need help with please

Any help is appreciated and welcomed.

I welcome your comments and suggestions as I would like to find out where I have gone wrong.

Kind regards
Den
Here the image containing the info when transmitting and receiving.

Transmitter code:

#include <VirtualWire.h>
#include <Keypad.h>
#include <string.h>
char key; //holds single key
char buffer[4]; //holds keys pressed
int i; //counter
//declare "code-holding" vars
char hcode[5] = {"1234"}; //5 or less digits/keys eg 1234 + NULL
char devcode[5]; //4 or less digits/keys eg 9999 + NULL 
char pcode[3] = {"21"}; //2 digits/keys eg 12 + NULL
char oocode[4] = {"234"}; //3 or less digits/keys eg 123 + NULL
char allcode[18]; //total array count including NULL's
//keypad vars and keymap
const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {8, 9, 10, 13}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {A0, A2, A1, A3}; //connect to the column pinouts of the keypad

   Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup(){

// Initialise the IO and ISR --radio
   vw_setup(2000);       // Bits per sec
   vw_set_tx_pin(7);
  Serial.begin(9600);
 
  //NULL the arrays
   buffer[0] = '\0'; //NULL the array
    //devcode[0] = '\0'; //NULL the array
   //pcode[0] = '\0'; //NULL the array
   //oocode[0] = '\0'; //NULL the array
   //allcode[0] = '\0'; //NULL the array
}
  
void loop(){
  i = 0; //set counter to 0
  buffer[0] = '\0'; //NULL the buffer array
  while( i < sizeof(buffer)) // removed this last one - 1)
  {
  
    key = keypad.getKey();
  if (key == '#')
     {
       Serial.print("Sent allcode = hcode, pcode, oocode, devcode"); //message that sending occurred
     memcpy(devcode, buffer, sizeof(buffer)); //copy ubffer to devcode     
      
showme(); //for debugging

   //prepare and format the message as allcode       
       sprintf(allcode, "%s,%s,%s,%s", hcode, pcode, oocode, devcode);
   //send it     
       vw_send((uint8_t *)allcode, strlen(allcode));
      Serial.print("This is allcode "); //show content of allcode 
       Serial.print(allcode); //show content of allcode
       Serial.println();
       
       vw_wait_tx(); // Wait until the whole message is gone
                   
       buffer[0] = '\0'; //NULL the array
       memset( devcode, 0, sizeof(devcode));// This line is to reset devcode
       memset( buffer, 0, sizeof(buffer));// This line is to reset buffer
       memset( allcode, 0, sizeof( allcode));// This line is to reset allcode
    break;
     }
         
   else if ( key != NO_KEY) //if(key)  is (or is it the same as) if(key != NO_KEY)
    {
     buffer[i] = key;
      i++;
      buffer[i]= '\0';
     
      }
       
  }
    
}

void showme(){ //for debugging  
        Serial.println();
       Serial.print("hcode :");
       Serial.write(hcode);
       Serial.println();
       Serial.print("pcode :");
       Serial.write(pcode);
       Serial.println();
       Serial.print("oocode :");
       Serial.write(oocode);
       Serial.println();
       Serial.print("devcode :");
       Serial.write(devcode);
       Serial.println();
       
        return;
}

Receiver code:

//Simple receiver

#include <VirtualWire.h>
    //const
       const int led_pin = 13;
       const int transmit_pin = 12;
       const int receive_pin = 3;
       const int transmit_en_pin = 3;
     
    //code vars
       int hcode[5]; // 4 digit code +1 for NULL (can it contain alpha numerics ABCD?)
       int devcode[5]; // 4 digits or lesss +1 for NULL (exactly what you enter on keypad a copy of buffer[])
       int pcode[3]; // 2 digit code +1 for NULL - could contain alpha numerics eg. A1
       int oocode[4]; // 3 digits or less +1 for NULL - numbers only 0 to 255 buill test with alpha numerics too

void setup()
{
       delay(1000);
       Serial.begin(9600);	// Debugging only
       Serial.println("Ready"); 

    // Initialise the IO and ISR
        vw_set_rx_pin(receive_pin);
        vw_setup(2000);	 // Bits per sec
    //vw_set_rx_pin(3);
        vw_rx_start();       // Start the receiver PLL running
    
        pinMode(led_pin, OUTPUT);
}

void loop()
{
        uint8_t buf[VW_MAX_MESSAGE_LEN];
        uint8_t buflen = VW_MAX_MESSAGE_LEN;
        buf[0] = '\0'; //NULL the array
        if (vw_get_message(buf, &buflen)) // Non-blocking
    {
	int i;//counter

        digitalWrite(led_pin, HIGH); // Flash a light to show received good message
     // Message with a good checksum received, dump it.
	Serial.print("Got: ");
	
    for (i = 0; i < buflen; i++)
	{
     //sscanf((char*)buf,"%d,%d,%d,%d",&hcode,&pcode,&oocode,&devcode); // Converts a string to an array

        Serial.print((char)buf[i]); //show content of buffer
	 Serial.print(' ');
	}

        digitalWrite(led_pin, LOW);
        
     //for debugging sscanf line
         Serial.println();
        Serial.print("hcode: ");
        Serial.print((char)hcode[5]);
         Serial.println();
        Serial.print("pcode: ");
        Serial.print((char)pcode[3]);
         Serial.println();
        Serial.print("oocode: ");
        Serial.print((char)oocode[4]);
         Serial.println();
        Serial.print("devcode: ");
        Serial.print((char)devcode[5]);
         Serial.println();

    }
}

When are
you planning
to learn
to use
Tools + Auto Format?

I give up on chasing your code all over the place.

Your image tags are hosed, so your image doesn't appear. But, we don't want to see pictures of your serial data anyway. Copy and paste the TEXT!

Hi Paul

Wow what a difference auto-format makes ..thanks for that tip !
Here is the transmitter code (now auto-formatted )

#include <VirtualWire.h>
#include <Keypad.h>
#include <string.h>
char key; //holds single key
char buffer[4]; //holds keys pressed
int i; //counter
//declare "code-holding" vars
char hcode[5] = {
  "1234"}; //5 or less digits/keys eg 1234 + NULL
char devcode[5]; //4 or less digits/keys eg 9999 + NULL 
char pcode[3] = {
  "21"}; //2 digits/keys eg 12 + NULL
char oocode[4] = {
  "234"}; //3 or less digits/keys eg 123 + NULL
char allcode[18]; //total array count including NULL's
//keypad vars and keymap
const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
  {
    '1','2','3','A'  }
  ,
  {
    '4','5','6','B'  }
  ,
  {
    '7','8','9','C'  }
  ,
  {
    '*','0','#','D'  }
};
byte rowPins[ROWS] = {
  8, 9, 10, 13}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {
  A0, A2, A1, A3}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup(){

  // Initialise the IO and ISR --radio
  vw_setup(2000);       // Bits per sec
  vw_set_tx_pin(7);
  Serial.begin(9600);

}

void loop(){
  i = 0; //set counter to 0
  buffer[0] = '\0'; //NULL the buffer array
  while( i < sizeof(buffer)) // removed this last one - 1)
  {

    key = keypad.getKey();
    if (key == '#')
    {
      Serial.print("Sent allcode = hcode, pcode, oocode, devcode"); //message that sending occurred
      memcpy(devcode, buffer, sizeof(buffer)); //copy ubffer to devcode     

      showme(); //for debugging

      //prepare and format the message as allcode       
      sprintf(allcode, "%s,%s,%s,%s", hcode, pcode, oocode, devcode);
      //send it     
      vw_send((uint8_t *)allcode, strlen(allcode));
      Serial.print("This is allcode "); //show content of allcode 
      Serial.print(allcode); //show content of allcode
      Serial.println();

      vw_wait_tx(); // Wait until the whole message is gone

      buffer[0] = '\0'; //NULL the array
      memset( devcode, 0, sizeof(devcode));// This line is to reset devcode
      memset( buffer, 0, sizeof(buffer));// This line is to reset buffer
      memset( allcode, 0, sizeof( allcode));// This line is to reset allcode
      break;
    }

    else if ( key != NO_KEY) //if(key)  is (or is it the same as) if(key != NO_KEY)
    {
      buffer[i] = key;
      i++;
      buffer[i]= '\0';

    }

  }

}

void showme(){ //for debugging  
  Serial.println();
  Serial.print("hcode :");
  Serial.write(hcode);
  Serial.println();
  Serial.print("pcode :");
  Serial.write(pcode);
  Serial.println();
  Serial.print("oocode :");
  Serial.write(oocode);
  Serial.println();
  Serial.print("devcode :");
  Serial.write(devcode);
  Serial.println();

  return;
}

And the receiver code (also auto-formatted)

//Simple receiver

#include <VirtualWire.h>
//const
const int led_pin = 13;
const int transmit_pin = 12;
const int receive_pin = 3;
const int transmit_en_pin = 3;

//code vars
char hcode[5]; // 4 digit code +1 for NULL (can it contain alpha numerics ABCD?)
char devcode[5]; // 4 digits or lesss +1 for NULL (exactly what you enter on keypad a copy of buffer[])
char pcode[3]; // 2 digit code +1 for NULL - could contain alpha numerics eg. A1
char oocode[4]; // 3 digits or less +1 for NULL - numbers only 0 to 255 buill test with alpha numerics too

void setup()
{
  delay(1000);
  Serial.begin(9600);	// Debugging only
  Serial.println("Ready"); 

  // Initialise the IO and ISR
  vw_set_rx_pin(receive_pin);
  vw_setup(2000);	 // Bits per sec
  //vw_set_rx_pin(3);
  vw_rx_start();       // Start the receiver PLL running

  pinMode(led_pin, OUTPUT);
}

void loop()
{
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;
  buf[0] = '\0'; //NULL the array
  if (vw_get_message(buf, &buflen)) // Non-blocking
  {
    int i;//counter

    digitalWrite(led_pin, HIGH); // Flash a light to show received good message
    // Message with a good checksum received, dump it.
    Serial.print("Got: ");

    for (i = 0; i < buflen; i++)
    {
      //sscanf((char*)buf,"%d,%d,%d,%d",&hcode,&pcode,&oocode,&devcode); // Converts a string to an array

      Serial.print((char)buf[i]); //show content of buffer
      Serial.print(' ');
    }

    digitalWrite(led_pin, LOW);

    //for debugging sscanf line
    Serial.println();
    Serial.print("hcode: ");
    Serial.print((char)hcode[5]);
    Serial.println();
    Serial.print("pcode: ");
    Serial.print((char)pcode[3]);
    Serial.println();
    Serial.print("oocode: ");
    Serial.print((char)oocode[4]);
    Serial.println();
    Serial.print("devcode: ");
    Serial.print((char)devcode[5]);
    Serial.println();

  }
}

Here is the output on the transmitter for (I used copy and paste but had to use putty because the Arduino serial monitor doesn't seem to catch all the selected characters to the clipboard for copy and paste and that's why I thought a picture might be easier for a side by side comparison.)

Sent allcode = hcode, pcode, oocode, devcode
hcode :1234
pcode :21
oocode :234
devcode :9999
This is allcode 1234,21,234,9999
Sent allcode = hcode, pcode, oocode, devcode
hcode :1234
pcode :21
oocode :234
devcode :687
This is allcode 1234,21,234,687
Sent allcode = hcode, pcode, oocode, devcode
hcode :1234
pcode :21
oocode :234
devcode :36
This is allcode 1234,21,234,36
Sent allcode = hcode, pcode, oocode, devcode
hcode :1234
pcode :21
oocode :234
devcode :5
This is allcode 1234,21,234,5
Sent allcode = hcode, pcode, oocode, devcode
hcode :1234
pcode :21
oocode :234
devcode :693B
This is allcode 1234,21,234,693B
Sent allcode = hcode, pcode, oocode, devcode
hcode :1234
pcode :21
oocode :234
devcode :123A
This is allcode 1234,21,234,123A

The last number in each send is the number entered via the keypad Eg. 9999

Here is the corresponding receiver output as each transmission is received:

Ready
Got: 1 2 3 4 , 2 1 , 2 3 4 , 9 9 9 9
hcode:
pcode:
oocode:
devcode:
Got: 1 2 3 4 , 2 1 , 2 3 4 , 6 8 7
hcode:
pcode:
oocode:
devcode:
Got: 1 2 3 4 , 2 1 , 2 3 4 , 3 6
hcode:
pcode:
oocode:
devcode:
Got: 1 2 3 4 , 2 1 , 2 3 4 , 5
hcode:
pcode:
oocode:
devcode:
Got: 1 2 3 4 , 2 1 , 2 3 4 , 6 9 3 B
hcode:
pcode:
oocode:
devcode:
Got: 1 2 3 4 , 2 1 , 2 3 4 , 1 2 3 A
hcode:
pcode:
oocode:
devcode:

I hope this clear this helps you or anyone else able to help me with the problem(s).
In the interim I looking back through the post with a fine-toothed comb and will try the top-down approach starting at the transmitter side to try and see what I'm doing wrong and where I have messed up.
I really would appreciate any further assistance and feedback.

Kind regards

Den

So, you are getting what you sent. That's good. Then, you do nothing with what you get, but you somehow expect the arrays to become populated. That's bad.