confused again with int byte char et al

I finished off one of the projects I am on during the night, it was the one with the MAX chips driving 6 x 7 seg displays via a radio link.

I thought I would battle on it as I hadnt used the chip before, but it went like a dream, and I was feeling chuffed with myself, despite the pressure to get all 3 jobs done.

So today I tried to finish of another job, which I thought would be simple scanning 24 switches, and sending their data to a robot for controlling the hydraulics.

I want to try and keep the duty cycle down and hopefully get these units approved in South Africa ( which is a minefield )

So I scan the 24 switches, using 3 CD4017s as a port expander, and read the data back to an input pin.
No problem there, and then I have managed to combine the individual switch readings into 3 integer bytes, which I can display on the monitor fine ( along with a security code 4th byte ) for instance it says it sent 101 , 296, 03, 091

I send them off to the SIM20 transceiver, with newsoftserial, ( I cant show all the code as its a mess of testing parts )

void transmit () {
 msg [0] = cust;                               //  msg [4] was declared as an unsigned int
 msg [1]  = Group0;
 msg [2] = Group1;
 msg [3] = Group2;

  SIM.print(msg [0]); 
  SIM.print(msg [1]); 
  SIM.print(msg [2]);  
  SIM.print(msg [3]);  
  
Serial.print ( " data gone " );
   delay ( 200 );  // ensures packet sent 

  }  // end of transmit

and I can see the 4 bytes going out on the scope on the data pin fine,

but when its received with several variations of the testing code all I can get is the numbers as 1,0,1, 2,9,6,3, 91

where what I need to be able to pick out each switch state is 0010010 10100010 01010011 00101010 for example :-

I always have a problem with this, how can you look at 56 for example, and know if it is number 56 or if its ascii for 8 ?

And I can see how to convert to int() etc, but can’t find how to get to B0001010 or whatever.

I have been working 20 hours a day for a week and its showing ! Can someone give me clue to the best method to do this ?

#include <NewSoftSerial.h>
#define RXPIN 14//   
#define TXPIN 15 // 
int   AC2DPin = 16;
char  serIn;  
#define SIMBAUD 9600
NewSoftSerial SIM(RXPIN, TXPIN);
int buf [4];
//char character = 0; // for incoming serial data
void setup() 
{
  Serial.begin(9600); 
  pinMode(AC2DPin, OUTPUT);
  digitalWrite ( 16, HIGH );
  SIM.begin(SIMBAUD);
}
//************************************
void loop() 
{
  if (SIM.available() > 0) {   // get incoming byte:    
    Serial.println(" something available "); 
    for (int w = 0; w <= 8; w++ ) {       //  or whatever I put here doesnt wotrk of course
      Serial.print(" w=  "); 
      Serial.print(w );
      buf [ w] =  SIM.read ();
      Serial.print("      value=  ");  
      Serial.println( (buf [w])); 
    } 
  }     
}

Boffin1:

Int buf[4];

for (int w = 0; w <= 8; w++ ) {       //  or whatever I put here doesnt wotrk of course
      buf [ w] =  SIM.read ();

Horrible things happen when you store 8 elements in a 4 element array.

LOL, thats just one of the things I was looking at to see how many individual "parts" of 3 digit numbers it would spew out :slight_smile:

It is the same for 4, but of course you just get the first four out.

I know I have been through this before, but I cant find which project I cracked it on ( probably with all you guys help ! )

I have managed to combine the individual switch readings into 3 integer bytes, which I can display on the monitor fine ( along with a security code 4th byte ) for instance it says it sent 101 , 296, 03, 091

The value 296 (decimal) requires 9 bits and won't fit into a byte!

296 (decimal) = 1 0010 1000 (binary) = 128 (hexadecimal)

If you try putting 296 (decimal) into a byte, you loose the most significant bit -
40 decimal = 0010 1000 (binary) = 28 (hex)

I always have a problem with this, how can you look at 56 for example, and know if it is number 56 or if its ascii for 8 ?

It's all just ones & zeros... Your application has to know what each byte represents. It also needs to know if two bytes in a row are part of an integer or other-larger type. In an EXE file, the byte(s) might represent a CPU instruction.

With standard file formats (WAV, MP3, JPG, etc.), there is a defined file structure. For example, in an 8-bit WAV file, each byte (after the header) represents an audio sample value. In a 16-bit WAV file, a sample is represented by two bytes in a row. The file-format specification and the file-header determine how the data has to be read.

You can open a file with a [u]Hex editor[/u] to see all of the bytes. Wherever there is a value that can be converted to an ASCII character, you will also see that ASCII character. Usually, you'll see some readable text in the header. When you get into the "real data", you'll also see characters. For example, wherever there is a value of 41 hex (65 decimal) you will see 'A'. But unless it's a text file, that 41 hex may not represent the letter A, and there's no way to tell unless you understand the file format.

From Arduino docs for Arduino .print()

Prints data to the serial port as human-readable ASCII text. This command can take many forms. Numbers are printed using an ASCII character for each digit.

Your data is sent as ASCII reresentations of integers, not as bytes. That is what .print() does by default.

An optional second parameter specifies the base (format) to use; permitted values are BIN (binary, or base 2), OCT (octal, or base 8), DEC (decimal, or base 10), HEX (hexadecimal, or base 16). For floating point numbers, this parameter specifies the number of decimal places to use. For example: Serial.print(78, BIN) gives "1001110"

If you add the BIN parameter the put will be as you desire.
Where is the data going? To a computer?

Joe

Thanks Guys, I forgot to set notify so only just seen your helpful replies.

The value 296 (decimal) requires 9 bits

yes I just typed imaginary numbers, well spotted.
Each of the byte represents the setting of 8 switches so 255 is the max.

If you add the BIN parameter the put will be as you desire.
Where is the data going? To a computer?

Thats great , I have used that before but couldn't find it , thanks again ( RTFM ! )

The data is going to another 328 to drive 24 solenoids on the robot via some 595s and MOSFETS

OK I have sent all the data as bytes, and at the receive end I can see 0, 136, and 24 as the three bytes ( thats just as I happened to connect four of the switch inputs on the remote control )

In fact if I Serial.print ( int ( buf [w] ) ); I see the IDnumber first and then the 3 data values:-

something available
w= 0 value= 101
w= 1 value= 0
w= 2 value= 136
w= 3 value= 24

and if I Serial.print ( buf [w], BIN ); I get

something available
w= 0 value= 1100101
w= 1 value= 0
w= 2 value= 10001000
w= 3 value= 11000

I have been looking at sorting out the bytes, but ( apart from the missing leading zeros ) this looks a lot like the bytes I set in a lookup table to send patterns to the LED displays via TPIC6B595 shift registers to light 7 segment displays.

If I just shiftout each of the 3 values to 3 shift registers, I shouldn’t have to parse anything ?

The TPICs can stand the 24v supply , and as they sink, I can connect the drains to the gates of the highside P chan mosfets that drive the solenoids.

Anyone see a fault with this before I start soldering :slight_smile:

Don't you need to take extra steps to restore the leading zeroes that using BIN will suppress?

I think you are right, I am not sure how to do that, if I start with a byte of 00000000 and then bitwise or | it with this data, might that work?

I am so scared of sending ascii to the shift register as the bytes wouldnt match the switches ( I could deduct 48 but I am not sure if that would work )

When I have got these projects out and get some time, I must study this, I hate being confused by simple things.

Don't you need to take extra steps to restore the leading zeroes that using BIN will suppress?

Not strictly necessary. We know that leading zeros are suppressed, so can the receiver of the message. The receiver will know that there are 8 digits. Check the length of the string and add on the extra zeros if desired.

and add on the extra zeros if desired.

Isn't that restoring the missing leading zeroes?

If I just shiftout each of the 3 values to 3 shift registers, I shouldn't have to parse anything ?

Here's my approach. The receiver get the string and checks its length. Lets say 6.
8-6 = 2. So I shift out 2 0's, then I shift out the remaining 6. "0" shift out 0 and "1" shift out 1.

The receiver gets "101". The length = 3. Shift out 8-3=5 zeros and then 1 0 1

We are using only a few simple if clauses and 2 simple loops.

Well using the scraps of code below, I have fed it out with shiftout, and the waveforms for the 3 bytes look great,( dont worry about the glitches on the green trace, thats the scope ) so now I can try soldering !

#include <NewSoftSerial.h>
#define RXPIN 14//   
#define TXPIN 15 // 
int   AC2DPin = 16;
char  serIn;  
#define SIMBAUD 9600
NewSoftSerial SIM(RXPIN, TXPIN);
#define latchPin 8  // rck
#define clockPin 19 // sck
#define dataPin 12  // ser in
#define blankPin 11  // notG
byte buf [4];

void setup() 
{
  Serial.begin(9600); 
  pinMode(AC2DPin, OUTPUT);
  digitalWrite ( 16, HIGH );
  pinMode(blankPin, OUTPUT);
  digitalWrite(blankPin, LOW);
  Serial.println("setup");
  pinMode ( latchPin, OUTPUT);
  pinMode ( clockPin, OUTPUT);
  pinMode ( dataPin, OUTPUT);
  SIM.begin(SIMBAUD);
}
//************************************
void loop() 
{
  if (SIM.available() > 0) {   // get incoming byte:    
    Serial.println(" something available "); 
    for (int w = 0; w <= 3; w++ ) {       
      Serial.print(" w=  "); 
      Serial.print(w);
      buf [ w] =  SIM.read ();
      Serial.print("      value=  ");  
      Serial.println( int (buf [w]));
    } 
    int s= buf [1]; 
    Serial.print("s =  ");  
    Serial.println(  (s));
    int t= buf [2]; 
    Serial.print("t =  ");  
    Serial.println( (t));
    int u= buf [3]; 
    Serial.print("u =  ");  
    Serial.println(  (u));
    digitalWrite(latchPin, LOW);            
    shiftOut(dataPin, clockPin, LSBFIRST, s);  
    shiftOut(dataPin, clockPin, LSBFIRST, t);
    shiftOut(dataPin, clockPin, LSBFIRST, u);  
    digitalWrite(latchPin, HIGH); 
  }     
}

Come to think of it, this is supposed to be o , 136, and 24 shifted out LSB first, hm something wrong there I think. No thats right !