RF22 wireless confusion data types

I have got myself confused again with the data types when sending data via RF22 library.

If I send this it goes through fine

Serial.println("Sending to rf22_server");
uint8_t data[] = "Hello World!";
rf22.send(data, sizeof(data));

So must I somehow send my 19 bytes of data as a string ( that I am trying to avoid, having been warned off them )

I have tried sending them individually, but it says " invalid conversion from 'uint8_t' to 'uint8_t*' so it looks like my lack of knowledge with pointers or whatever.

If I can string together my data into a string ( csv or whatever ) ? presumably I could send it as above, and parse out the 19 integers at the RX end ?

I am sure there is a much simpler way, but the rate I am going on this it will be Easter by the time I understand it :slight_smile:

So must I somehow send my 19 bytes of data as a string ( that I am trying to avoid, having been warned off them )

There are no problems whatsoever with strings. Strings, on the other hand, should be avoided, and probably are not supported by that library, anyway.

If I can string together my data into a string ( csv or whatever ) ? presumably I could send it as above, and parse out the 19 integers at the RX end ?

If you convert the 19 integers to a string, how will you tell one value from another? This string contains three values - "1456732". Can you tell what the three values are?

I have tried sending them individually, but it says " invalid conversion from 'uint8_t' to 'uint8_t*' so it looks like my lack of knowledge with pointers or whatever.

So you posted some other code for us to look at. I guess we're supposed to say something like "My, what pretty code." Well, OK.

My, what pretty code.

Merry Xmas Paul !

Quote
If you convert the 19 integers to a string, how will you tell one value from another? This string contains three values - "1456732". Can you tell what the three values are?
thats why I mentioned comma separated variables.

I didn't post the whole code because I havn't got this bit working with a days worth of different ideas, but I will post the rest below, the problem is with sending the array " blockChar " that I need to send . ( I only need to send 19 of them )
The array is indexed to the block number 1-32 of the LCD display.

The whole code is work in progress, I will change the ifs to case type selection later.

I can display it on the LCD display with no problem, and with my previous RF modules ( 4 times the price ) I could have sent it with VirtualWire, but I am trying to master these more intelligent ones.

In retrospect this isn't the ideal project to learn this but I don't have a choice.

There are 5 buttons to set the two 8 digit team names on a scoreboard, and a preset 2 digit period minutes.

These are displayed on an LCD, the remote goes into sleep, and the backlight goes of after a few seconds of inactivity, I still have to sort out what to switch off on the LCD for sleep, and some other minor functions.

The S button sends the data, the L and R buttons move the cursor left and right, and the Up and Down buttons scroll thorough the charachters ( fast forward when held down )

The code as requested is below ( I have had to split it into 2 posts as it was over the limit of characters )

#include <SPI.h>
#include <RF22.h>
#include <Keypad.h>  
#include <LiquidCrystal.h> // we need this library for the LCD commands
#include <avr/sleep.h>      // powerdown library
#include <avr/interrupt.h>  // interrupts library
// Singleton instance of the radio
RF22 rf22;
char key;
int botRow;
int backlightPin = 14;
int pin3 = 3; // Int1 interuppt pin

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
long sleep_count = 0;      // flag/counter to tell us to go sleep

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
int button;  // integer of button ascii number
int blinkLoop; // loopcount for the cursor blinking
char chars [] = {
  '_','0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I',
  'J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','-','.','?' };
uint8_t blockChar [32];  //  the actual character for each block to display and send  //8888888888888888888888888 was char
int q [32 ];
char msg [19]; // the two 8 char teamnames and the intital minutes plus PIN
int PIN = 101;  //  for first takealot text remote
///////////////////////////////////////  keypad settings ////////////////////
const byte ROWS = 2; // two rows
const byte COLS = 3; // three columns
char keys[ROWS][COLS] =   {       
  {
    'C','U','L'           } 
  ,  // row 1  //   CLEAR, UP, LEFT
  { 
    'S','R','D'          }  
  ,  // row 2    //  SEND , RIGHT ,  DOWN
};
byte rowPins[ROWS] = { 
  19, 18  }; 
byte colPins[COLS] = { 
  15,16,17}; // Create the Keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
////////////////////////////////////////////////////////////////////////////////
LiquidCrystal lcd(4,5,6,7,8,9); // define our LCD and which pins to user 
int block  ; //  0 - 31 character position numbers  0 - 15 top row, 16 - 32
unsigned long previousMillis = 0; 
//**************************************************************new interrupt
// *  Name:        pin2Interrupt, "ISR" to run when interrupted in Sleep Mode
void pin3Interrupt()
{
  /* This brings us back from sleep. */
}
//***************************************************************


void setup()

{
  Serial.begin(9600);
  lcd.begin(16, 2); // need to specify how many columns and rows are in the LCD unit
  //lcd.clear();      // this clears the LCD. You can use this at any time
  Serial.println(" setup");     
  for ( int x = 0; x <=31; x++ ) { //   clears all the blocks to underscore which will show as blank on board  
    blockChar [x] = 0 ;   
  }
  lcd.display(); //enable lcd display
  lcd.clear(); 
  blinkLoop = 0;
  resethome ();  //  clears display and zeros cursor
  block = 0;  //  start at block 0 top left 
  for ( int x = 0; x <=31; x++ ) { //  clear all values for all blocks
    q [x] = 0 ;  
  }
  pinMode (backlightPin , OUTPUT );

  lcd.setCursor(10,0);

  lcd.print("min=");  //  prints the period minutes on top right, and returns cursor to 1,0
  lcd.setCursor(1,0);
  block = 1;
  if (!rf22.init())
    Serial.println("RF22 init failed");
  // Defaults after init are 434.0MHz, 0.05MHz AFC pull-in, modulation FSK_Rb2_4Fd36

  if (!rf22.setFrequency(434.0))
    Serial.println("setFrequency failed");
  if (!rf22.setModemConfig(RF22::GFSK_Rb2Fd5))
    Serial.println("setModemConfig failed");
}  
void loop()   
{ 
  if (sleep_count>100000){                      // check if we should go to sleep because of "time" --> Try shorter versions of this
    sleep_count=0;                           // turn it off for when we wake up
    Serial.println("Sleep");               // for debug only
    digitalWrite(15, LOW);// set the columns low before sleeping, otherwise Keypad leaves them high and Rows have nothing to pull low.
    digitalWrite(16,LOW); 
    digitalWrite(17, LOW);

    digitalWrite(backlightPin, LOW);
    Serial.println(" backlight off ");
    enterSleep();                             // call Sleep function to put us out
    //  THE PROGRAM CONTINUEs FROM HERE after waking up in enterSleep()
  }

  blinkLoop++; //   blink cursor so shows difference between E and F for example
  if (blinkLoop > 500) {
    lcd.cursor() ;
  } 
  else { 
    lcd.noCursor() ; 
  } 
  if (blinkLoop > 1000) {
    blinkLoop = 0;
  }
  char key = keypad.getKey();                 // reading the keypad
  if(key)  {          // same as if(key != NO_KEY)- did something change?        

    Serial.print("key read =");   
    Serial.println(key);
    button = key; // integer version of ascii 
    checkbutton ();  // actions for each key 

    sleep_count = 0;     
  } 
  sleep_count ++;  
  if ( keypad.getState() == HOLD )
  {
    Serial.print("key held =");   
    Serial.println(key);  
    if (( millis() - 250) > previousMillis ) 
    {
      previousMillis = millis();    
      checkbutton ();  // actions for each key 
    }
  }
}
void resethome () {

  lcd.clear();  
  lcd.display(); 
  lcd.setCursor(10,0);
  lcd.print("min=");  //  prints the period minutes on top right, and returns cursor to 1,0
  lcd.setCursor(1,0);
  block = 1;
}
void checkbutton () {

  Serial.print("key pressed =  "); 
  Serial.println(button);
  if ( button == 67 ) {    //  key = C or ascii 67  Clear
    Serial.print("key ch =  "); 
    Serial.println(key);
    resethome () ;
    Serial.println("key check = cancel  C  ");   
  }
  //*****************************************************************************  
  if ( button == 83 ) {//  key = S or ascii  83  Send
    Serial.print("key check =send S ");   //  still got to write this bit
  }    
  //******************************************************************************
  if ( button == 76 ) {   //  key = L or ascii  85  LEFT
    Serial.print("key check =   L  cursor left ");  
    block = block--;
    if ( block < 1 ) { 
      block = 24 ; 
    }
    if ( block ==13 ) { 
      block =8;
    }
    if ( block ==16 ) { 
      block =15;
    }
    Serial.print("block ");
    Serial.print(block);
    if ( block >15 ) {  
      // botRow = block - 16 ;      
      lcd.setCursor(block-16 ,1); 
    }
    else {   
      lcd.setCursor(block,0);
    }
  }
  //*****************************************************************************    
  if ( button == 82 ) {   //  key = R or ascii 82
    Serial.print("key check = R   cursor right  "); 
    block = block++;
    if ( block > 24 ) {       
      block = 1 ;    
    }  
    if ( block ==9 ) {       
      block = 14 ;    
    }
    if ( block ==16 ) {       
      block = 17 ;    
    }

    Serial.print("block ");
    Serial.print(block);
    if ( block >15 ) {  
      // botRow = block - 16 ;      
      lcd.setCursor(block-16 ,1); 
    }
    else {   
      lcd.setCursor(block,0);
    }
  }

and the last bit :-

  ///***********************************************************************  
  if ( button == 85 ) {   //  key = U or ascii 85
    Serial.print("key check = U   char up one  ");   
    q [block] ++;    
    if ( q[block] >39 ) { 
      q[block]=0 ; 
    }
    Serial.print("q = "); 
    Serial.println(q[block]);     
    blockChar [block] = chars [ q[block] ];    
    Serial.print("q ");
    Serial.print(block);
    Serial.print("=  ") ;
    Serial.println(q[block]); 
    lcd.print(blockChar [block]);  
    if ( block >15 ) {  
      botRow = block - 16 ;
      lcd.setCursor(botRow+1 ,1); 
    }
    else {   
      lcd.setCursor(block,0);
    }
  }
  //*************************************************************************  
  if ( button == 68 ) {   //  key = D or ascii 68
    Serial.print("key check = D   char down one  ");  
    q [block] --;    
    if ( q[block] <0 ) { 
      q[block]=39 ; 
    }
    Serial.print("q = "); 
    Serial.println(q[block]);     
    blockChar [block] = chars [ q[block] ];    
    Serial.print("q ");
    Serial.print(block);
    Serial.print("=  ") ;
    Serial.println(q[block]); 
    lcd.print(blockChar [block]);    
    if ( block >15 ) {  
      botRow = block - 16 ;
      lcd.setCursor(botRow,1); 
    }
    else {   
      lcd.setCursor(block,0);
    }
  }
  sendata ();
}
void enterSleep()
{
  /* Setup pin2 as an interrupt and attach handler. */
  attachInterrupt(1, pin3Interrupt, FALLING);
  delay(50); // need this?
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // setting up for sleep ...
  sleep_enable();                       // setting up for sleep ...
  ADCSRA &= ~(1 << ADEN);
  PRR = 0xFF;
  sleep_mode();                         // now goes to Sleep and waits for the interrupt
  /* The program will continue from here after the interrupt. */
  detachInterrupt(1);                 //disable interrupts while we get ready to read the keypad 
  PRR = 0x00;
  /* First thing to do is disable sleep. */
  sleep_disable(); 
  // set all the keypad columns back high so can read keypad presses again
  digitalWrite(15, HIGH);
  digitalWrite(16, HIGH); 
  digitalWrite(17, HIGH);
  digitalWrite(backlightPin, HIGH);  
  Serial.println(" backlight on "); 
  // then go to the void Loop()
}  //  end of entersleep

void sendata () {
  for ( int f = 0; f<=35; f++ ){
 Serial.print(" block  ");Serial.print(f); Serial.print(" character =   "); Serial.println(blockChar [ f ]);   }
   // this lists all the characters set for each block OK
    Serial.println("Sending to rf22_server");
    
//    This is where I have got stuck 
// Send a message to rf22_server
//uint8_t data[] = "Hello World!";
//uint8_t data[] = blockChar [1];
 for ( int f = 0; f<=35; f++ ){
// Serial.print(" block  ");Serial.print(f); Serial.print(" character =   "); Serial.println(blockChar [ f ]);   }rf22.send(blockChar [f], sizeof(blockChar [f]));
rf22.waitPacketSent();    }
}

In your last bit of code, shall we assume that you really mean to comment out
everything on the 2nd to last line, before waitpacketsent?

Yes the last bit is where I have been trying all sorts of ideas, I have no code for that part, I suppose I should have left it blank

I guess I don't see the point of looking at sendata() if you're not sending any data.

In any case, I've not used the RF22 library, but recently bought JeeNodes, so am
interested in how to do this stuff. I should think all you have to do is create a char
data array, as follows, and fill it initially or more likely with runtime data,

uint8_t data[] = "Hello World!";
rf22.send(data, sizeof(data));

uint8_t data2[16] = { 0, 1, 2, 3, ... };
rf22.send(data2, #tosend);

I would get this all working properly as a test sketch "before" embedding into a real
program.

Yes thats what I am trying, the part
for ( int f = 0; f<=35; f++ ){
Serial.println(blockChar [ f ]); }

will serial print all the relevant data for each block, but I cant seem to figure out how to get this out on RF22.

I have tried changing the data type where I declare the blockChar but I seem to come unstuck on getting my head round the data types ( and * and # )

I will try your suggestion, but where does the #tosend come from ?

where does the #tosend come from ?

That's for you to determine, per each individual msg.

I've been looking at this page, I assume you're using this library,
http://www.open.com.au/mikem/arduino/RF22/classRF22.html#a2f6f295a313e1ebf244b91338ed22f13

boolean RF22::recv	(	uint8_t * 	buf,
uint8_t * 	len 
)		
Turns the receiver on if it not already on. If there is a valid message available, 
copy it to buf and return true else return false. If a message is copied, *len is 
set to the length (Caution, 0 length messages are permitted). You should be 
sure to call this function frequently enough to not miss any messages It is 
recommended that you call it in your main loop.

Parameters:
[in]	buf	Location to copy the received message
[in,out]	len	Pointer to available space in buf. Set to the actual 
  number of octets copied.
Returns:
true if a valid message was copied to buf
Examples:
rf22_client.pde, rf22_server.pde, rf22_snoop.pde, and rf22_test.pde.

References available(), and clearRxBuf().

In your array blockChar[], the name blockChar itself is just a pointer, so you'd use
recv(blockChar, numbytes).

I assume recv() should be used with available(), just like Arduino Serial.available(). Unfortunately,
it doesn't seem to return the #bytes received, so maybe you have to guess.

boolean RF22::available	(		)	
Starts the receiver and checks whether a received message is available. This can be 
called multiple times in a timeout loop

Returns:
true if a complete, valid message has been received and is able to be retrieved 
by recv()

OK this works, I have moved the sendata() to only send when the Send button is pressed.

I am monitoring the receiver, and it gets all 32 values of the blocks, but it takes about 2 seconds to go through, which wouldnt matter...
but I will try sending all the data together ( and just send the 19 values I need )

void sendata () {
  Serial.println("Sending to rf22_server");
  for ( int f = 0; f<=32; f++ ){
    uint8_t data[] = { 
      (blockChar [ f ])         };
    rf22.send(data, sizeof(data));
  }
  rf22.waitPacketSent();    
}
    uint8_t data[] = { 
      (blockChar [ f ])         };
    rf22.send(data, sizeof(data));

This is unnecessarily complicated. Just cast blockChar[f] to the right type.

rf22.send((unit8_t *)blockChar[f], sizeof(blockChar[f]));

Thanks I am starting to get the idea.

I have selected just the various data I want to send now, plus an extra PIN, and it transmits fast now

void sendata () {
 
    uint8_t data[19] = {PIN, blockChar [ 1 ],blockChar [ 2 ],blockChar [ 3 ],blockChar [ 4 ],blockChar [ 5 ],
    blockChar [ 6 ],blockChar [ 7 ],blockChar [ 8 ],blockChar [ 14 ],blockChar [ 15 ],blockChar [ 17 ],
    blockChar [ 18 ],blockChar [ 19 ],blockChar [ 20 ],blockChar [ 21 ],blockChar [ 22 ],blockChar [ 23 ],blockChar [ 24 ],
            };
   Serial.print("data sending"); // Serial.println(data[19]);
    rf22.send(data, sizeof(data));
  //}
  rf22.waitPacketSent();    
}

Thats enough for tonight , its half past Christmas already :slight_smile:

Boffin1:
I am monitoring the receiver, and it gets all 32 values of the blocks, but it takes about 2 seconds to go through,

  for ( int f = 0; f<=32; f++ ){

uint8_t data[] = {
      (blockChar [ f ])         };
    rf22.send(data, sizeof(data));
  }

This was slow because what this code did was to send your "entire" data[] array 32 times,
with as many bytes each time as the array data[] was declared to be initially, not just
each byte you loaded up from blockChar[]. The following would go fast, and send just
the proper bytes of blockChar[],

    rf22.send(blockChar, 32);

Thanks for your help guys, Its working fine now ( I was sending all 32 blocks just to test, I now send just the 19 blocks that are used )