Converting a string to binary array.

Hello,

Just started programming on Arduino the other day, and can't quite figure out a few things.

So here's the flow of what I'm trying to accomplish.

-Prompt user for message to transmit (Done)

-Store input as String (Done)

-Convert String to binary (Not done)

-Transmit binary with LED (Done)

-Receive binary with Photoresistor (Done)

-Convert binary to String (Not done)

-Print String to LCD (Done)

I can create a generic "int myMsg={HIGH, LOW, HIGH, LOW}," send that to the LED, receive it on the other side, and print it to the Serial Monitor as 1010.

I think I might be going about this in the wrong way.

I used a bitRead loop to convert a String to binary and print that to the monitor one digit at a time, but I haven't been able to store the entire String to an array of binary octets. I'm pretty new to this language.

Any tips are appreciated.

Thanks.

Post the code you have and we can try to help.

This sketch prompts for a message, converts each character to ascii, and each ascii value to binary.

#define laser 12
String message; //initiate variable
String prompt = "What is your message?"; //initiate prompt
String confirm = "Your message is "; //repeats message


void setup() {
  Serial.begin(9600); //initiate serial monitor
  pinMode(laser, OUTPUT);
}

void loop() {
  Serial.println(prompt); //ask for input

  while (Serial.available() == 0); { //wait for input

  }
  message = Serial.readString(); //write input to variable
  Serial.println(confirm); //repeat message
  Serial.println(message); //
  
  for(int i=0;i<message.length(); i++){
    char character = message.charAt(i);
 
    for(int i=7; i>=0; i--){
      byte bytes = bitRead(character,i);
      Serial.print(bytes);
    }

    Serial.println("");
}
}

These sketches come from youtube

It covers the basics of what I'm trying to do, but doesn't cover how to convert a text input into the

int message={HIGH,LOW,HIGH,LOW} format

#define LASERPIN 12

void setup() {
  // put your setup code here, to run once:
  pinMode(LASERPIN, OUTPUT);

}

void loop() {
  // 01011010
  int bits[] = {LOW, HIGH, LOW, HIGH, HIGH, LOW, HIGH, LOW};
  
  //start bit
  digitalWrite(LASERPIN, HIGH);
  delay(10);
  digitalWrite(LASERPIN, LOW);

  for (int i = 0; i < 8; i++) {
    digitalWrite(LASERPIN, bits[i]);
    delay(10);
  }

  digitalWrite(LASERPIN, LOW);

  delay(1000);
}
#define SOLARPIN A0
#define THRESHOLD 10

int ambientReading = 0;

void setup() {
  pinMode(SOLARPIN, INPUT);
  Serial.begin(9600);

  ambientReading = analogRead(SOLARPIN);
}

void loop() {

  int reading = analogRead(SOLARPIN);
  int bits[8];

  // Listening for the start bit
  if (reading > ambientReading + THRESHOLD) {
    for (int i = 0; i < 8; i++) {
      if (analogRead(SOLARPIN) > ambientReading + THRESHOLD) {
        bits[i] = 1;
      }
      else {
        bits[i] = 0;
      }
      delay(10);
    }

    for (int i = 0; i < 8; i++) {
      Serial.print(bits[i]);
    }
    Serial.println("");
    
  }
}

From what I've gathered, converting a character to ascii, and ascii to binary is built in, so I shouldn't need to include a library for that conversion.

Using bitRead on the letter 'a' returns its ascii value, 97, in binary, 01100001.

I don't how to create an array of octets, or if that's even the direction I should be going.

Thanks for any help you can offer.

With much spinning of wheels, I got this to work.

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);

}

void loop() {
  // put your main code here, to run repeatedly:
  
  String message = "abc";
  int bytes[24];
  
  for(int i=0;i<message.length(); i++){
    char character = message.charAt(i);
 
    for(int i=7; i>=0; i--){
      bytes[i] = bitRead(character,i);
      Serial.print(bytes[i]);
      delay(100);
    }
}
delay(5000);
Serial.println("");
}

Working on the next step.

#define laser 12
String message; //initiate variable
String prompt = "What is your message?"; //initiate prompt
String confirm = "Your message is "; //repeats message
int bytes[256];
int data[256];


void setup() {
  Serial.begin(9600); //initiate serial monitor
  pinMode(laser, OUTPUT);
}

void loop() {
  Serial.println(prompt); //ask for input

  while (Serial.available() == 0); { //wait for input

  }
  message = Serial.readString(); //write input to variable
  Serial.println(confirm); //repeat message
  Serial.println(message); //

  for(int i=0;i<message.length(); i++){
    char character = message.charAt(i);
 
    for(int i=7; i>=0; i--){
      bytes[i] = bitRead(character,i);
      Serial.print(bytes[i]);
    }
}
Serial.println("");  
}

Prompts for input, outputs binary.

Next step is converting ones and zeros to HIGHs and LOWs.

My latest attempt.

Trying to convert "a" to 97, and 97 to 01100001, and 01100001 to

LOW, HIGH, HIGH, LOW, LOW,LOW,LOW,HIGH

#define laser 12
String message; //initiate variable
String prompt = "What is your message?"; //initiate prompt
String confirm = "Your message is "; //repeats message
int bytes[256];
int data[256];


void setup() {
  Serial.begin(9600); //initiate serial monitor
  pinMode(laser, OUTPUT);
}

void loop() {
  Serial.println(prompt); //ask for input

  while (Serial.available() == 0); { //wait for input

  }
  message = Serial.readString(); //write input to variable
  Serial.println(confirm); //repeat message
  Serial.println(message); //

  for(int i=0;i<message.length(); i++){
    char character = message.charAt(i);
 
    for(int i=7; i>=0; i--){
      bytes[i] = bitRead(character,i);
      Serial.print(bytes[i]);
    }
}
Serial.println("");
for(int i=256;i>=0;i--){
   if(bytes[i]==1){
    data[i]=HIGH;
   }
   else{
    data[i]=LOW;
    Serial.print(data[i]);
   }
}
}

Clearly, I'm doing something wrong.

What I think I've been able to do is convert each character to a binary octet.

From there, I need to convert that array to another array of HIGHs and LOWs.

Seems like a simple operation to me, but nothing I've come across online covers this.

Been spinning my wheels for days on it.

if code in post #6 works (ie generated your binary array correctly) then what you are trying to do in post #7 is pointless.

digitalWrite(pin, bytes[ i ]) will output HIGH for bytes[ i ]=1 and LOW for bytes[ i ]=0

hope that helps....

Just to expand on what sherzaad has said here...

Each character IS an octet (same thing as a byte). So you are already doing a conversion to highs and lows, as you put it.

But, some things to note - for every character you read from serial, you're writing to the first 8 bytes of the "bytes" array. As it is written now, you are only writing to those first 8 bytes. You could change this from

for(int i=7; i>=0; j--){
      bytes[i] = bitRead(character,i);
      Serial.print(bytes[i]);
}

to

for(int j=7; j>=0; j--){
      bytes[j + i * 8] = bitRead(character,j);
      Serial.print(bytes[j + i * 8]);
}

This way, you will actually write past the first 8 elements of bytes, so you can actually encode multiple characters.

Doing that, you'll still run into a problem with the second loop, which is that you are emitting all 256 "highs" and "lows", but you're not necessarily writing all 256 highs and lows.

All this to ask, why are you writing to an intermediate array (bytes) and not just emitting immediately? Do you plan on doing something more with that data?

Just do this:

for(int j=7; j>=0; j--){
      digitalWrite(laser, bitRead(character,j));
      Serial.print(bitRead(character,j));
}

and remove that whole bottom for loop.

Thank you everyone.

binaryfissiongames:
All this to ask, why are you writing to an intermediate array (bytes) and not just emitting immediately? Do you plan on doing something more with that data?

Because I'm used to MATLAB, and I'm spoiled. I like being able to check an array after its loops run to make sure I did it right. I can see that's not a common thing on this side of the house.

I'll play with the stuff others suggested and see if it comes together.

Thanks again everyone.

Successfully sending and receiving data.

//Binary Transmitter
#define laser 12
String message; //initiate variable
String prompt = "What is your message?"; //initiate prompt
String confirm = "Your message is "; //repeats message
int bytes[256];
int data[256];


void setup() {
  Serial.begin(9600); //initiate serial monitor
  pinMode(laser, OUTPUT);
}

void loop() {
  Serial.println(prompt); //ask for input

  while (Serial.available() == 0); { //wait for input

  }
  message = Serial.readString(); //write input to variable
  Serial.println(confirm); //repeat message
  Serial.println(message); //
  digitalWrite(laser,HIGH);
  delay(10);
  digitalWrite(laser,LOW);

  for(int i=0;i<message.length(); i++){
    char character = message.charAt(i);
 
    for(int i=7; i>=0; i--){
      bytes[i] = bitRead(character,i);
      Serial.print(bytes[i]);
      if(bytes[i]==1){
        digitalWrite(laser,HIGH);
      }
      else{
        digitalWrite(laser,LOW);
      }
      delay(50);//same delay per bit as transmitter (10ms is too short for LED)                  
    }
    Serial.println("");
}
digitalWrite(laser,LOW);
Serial.println("");
}
//Binary Receiver
#define receiver A0
#define tolerance 30

int ambient = 0;

void setup() {
  pinMode(receiver, INPUT);
  Serial.begin(9600);

  ambient = analogRead(receiver);
}

void loop() {

  int reading = analogRead(receiver);
  int bits[8];

  // Listening for the start bit
  if (reading > ambient + tolerance) {
    delay(20);//longer delay than transmitter to stop the start bit from being mistaken for a data bit
    for(int i=0;i<4;i++){ //maximum characters controled here
      for (int i = 0; i < 8; i++) {//octet loop            
      if (analogRead(receiver) > ambient + tolerance) {
        bits[i] = 1;
      }
      else {
        bits[i] = 0;
      }
      Serial.print(bits[i]);
      delay(50);//same delay per bit as transmitter (10ms is too short for LED)
    }
    Serial.println("");      
    }    
    Serial.println("");    
  }
}

Next step is translate back to characters.

If anyone has any tips for where I should be looking to convert back to characters, I'm all ears.

Just do the same things, but in reverse. :slight_smile:

Yeah, pretty much do the opposite :stuck_out_tongue:
look at the bitWrite function.

binaryfissiongames:
All this to ask, why are you writing to an intermediate array (bytes) and not just emitting immediately? Do you plan on doing something more with that data?

zjcrawford:
Because I'm used to MATLAB, and I'm spoiled. I like being able to check an array after its loops run to make sure I did it right. I can see that's not a common thing on this side of the house.

Arduinos have (very) limited RAM. This is why, rather than writing your values to an array, it is best to just print them directly to the Serial monitor.
If I were to recite a list of numbers, dozens of numbers long, for you to write down, would you wait for me to finish reciting the entire list before you began to write? Of course not! You would write down each number as soon as you heard it. Why? Because otherwise your memory would be overwhelmed with all the numbers.
Same thing with an Arduino.

It's working.

#include <LiquidCrystal.h>

LiquidCrystal lcd(8,9,4,5,6,7);

//Binary Receiver
#define receiver A0
#define tolerance 30

int ambient = 0;

void setup() {
  pinMode(receiver, INPUT);
  Serial.begin(9600);
  lcd.begin(16,2);

  ambient = analogRead(receiver);
}

void loop() {

  int reading = analogRead(receiver);
  int msg[4];
  int bits[8];
  byte binary=0b00000000;
  char character;

  // Listening for the start bit
  if (reading > ambient + tolerance) {
    lcd.clear();
    delay(20);//longer delay than transmitter to prevent the start bit from being mistaken for a data bit
    for(int i=0;i<64;i++){ //maximum characters controled here      
      for (int i=7;i>=0;i--) {//octet loop           
      if (analogRead(receiver) > ambient + tolerance) {        
        bitWrite(binary,i,1);
      }
      else {
        bitWrite(binary,i,0);
      }      
      delay(40);//same delay per bit as transmitter (10ms is too short for LED)
    }
    char character=binary;
    Serial.print(character);
    lcd.print(character);    
    }   
    Serial.println("");   
  }
}

odometer:
Arduinos have (very) limited RAM. This is why, rather than writing your values to an array, it is best to just print them directly to the Serial monitor.
If I were to recite a list of numbers, dozens of numbers long, for you to write down, would you wait for me to finish reciting the entire list before you began to write? Of course not! You would write down each number as soon as you heard it. Why? Because otherwise your memory would be overwhelmed with all the numbers.
Same thing with an Arduino.

I understand that, and I did take it that way. The process breaks down on long messages because the sender and receiver are falling out of sync. I used to work in communications, so I'm familiar with the need for unified timing to keep everything on the same beat, but I haven't studied actually programming it yet.

Thanks for all the help, folks.