Store txt as variable

Hello,

This is a really simple problem I think, but I can't find the solution, as I don't know anything about C++. I just need to send a message to an Arduino Uno to a Nano through WiFi using NRF24L01 modules. Everything is working now, but I only sent a pre-written message, like this :

const char message[] = "Hello World !!!"

My point is, I'll use a Python code to create a message I will store in a txt file. I couldn't find anywhere a method to acccess this file and store its content in a variable. Could someone tell me how can I do it ?

Thanks !

An Arduino with an SD card socket or module can read text files on the card and send text data.

If you don't know C/C++, expect a significant learning curve in getting that to work.

Hi,

I don't need, and I would like to avoid, using a SD card. I just need to store what is inside my file in the variable "message". Is it impossible in C/C++ ?

In Python I would use something like that :

file = open('path_to_file', 'r')
message = file.readline() 

But I don't know how to do it in the Arduino IDE.

Thanks,
Archer

The rf24 radios are not WiFi. You can send a message through the rf24 radio from the Nano to the Uno and save the message in a string (null terminated character array) variable. The Uno (nor Nano) has no file system. What do you want to do with the message after it is received?

Robin2's simple rf24 tutorial is what I used to get my radios to work. One of the biggest hurdles to getting the rf24 radios to work is supplying them with 3.3V power with sufficient current. That is covered in the tutorial.

Programs in an Arduino are stored in nonvolatile memory upon upload, and must be self contained.

You can prepare a C/C++ compatible file with various selectable lines of text, to be included in the program when it is compiled and uploaded.

See https://www.arduino.cc/reference/en/language/variables/utilities/progmem/ for some examples. Hint: avoid tutorials that use String objects, use character arrays instead.

Where does this Python code and text message file reside?
How big is the text file?

Is there a Serial connection between the Python app and the Arduino? If so, the Arduino and the Python app can communicate with each other and the Python app can pass the message to the Arduino.

The Arduino sketch runs on a separate computer so it doesn't have access to files on your PC like Python on the PC does.

If the Arduino is connected by USB cable to your PC you could have the Python program send the messages to the Arduino as if it were a serial port. That is the most common way of getting data to an Arduino from a PC.

Hello,

My bad.

Just print it, or ideally store it in another file on my pc.

Okay, I actually didn't think about that. I can upload my message on the Arduino. The point is, I must not type in the message by myself. I need to take it from a file.

On my computer. Currently, I have a series of folders which ends with two folders : "Code" and "Arduino". The message and the Python code are in "Code", while my Arduino sketches are in "Arduino". But I can change that anytime if required.

Not much. For now it is "this is a test". But it's going to be in binary in the end.

I did not know that was possible ? I think it could solve my problem. Could you tell me more ?

I tried to use pyFirmata to do that but I couldn't find anywhere a relevant and complete lesson. Do you have a source ?

Where does this "file" come from?

Unless it is correctly formatted, it cannot be automatically included in a C/C++ Arduino program.

The more, correct and clear information you supply, the quicker you will get useful answers. So, I suggest that you take a moment and give us some useful details about your project.

"Firmata" is an Arduino sketch that lets a PC read and write digital pins and read analog input pins. "pyFirmata" is a library for communication with the Firmata sketch. It will not work with an Arduino sketch that you write.

Look for examples of communicating to an Arduino sketch through serial.

You will just use pySerial to open a serial connection over the com port to the Arduino. There are many examples and tutorials online. Here's a starter.
https://create.arduino.cc/projecthub/ansh2919/serial-communication-between-python-and-arduino-e7cce0

Hi,

I don't know how it wasn't clear but I'm sorry if it is. I have (I will at least) have a Python code which will transform a message (string) into a binary sequence, through the Huffman code. Then I add it CRC's bits, and store everything in a file. I, now, want to send this sequence through my NRFs module. The file will be stored somewhere on my computer, anywhere I want.

I understood that, but couldn't find a way to learn to use pyFirmata on it's own. Therefore, as I already have a Python code which will store the binary sequence in a folder, I was looking for a way to extract the content of this file and send it through my Arduino/NRFs setup. I understand through your answers it's not possible.

If I understood well, I need to use only Python (which I'd prefer if I could find an effective lesson for pyFirmata) or a SD card, am I right ?

When I installed pyFirmata, it also installed pySerial. I thought the latter was part of pyFirmata. Checking the link right now !

Thank you all and please excuse my inexperience.
Archer

How are we supposed to know that the text was PROGRAM GENERATED, unless you tell us?

In my first message, I said :

I think we both misunderstood each other, sorry for that.

Could you tell me more ? I do not manage to use the NRF modules with Python. Do I still need to upload a sketch on the arduino ? Documentation say it will be overruled by the Python code running. If yes, how do I tell the Arduino to send the message through the NRF once I've done the serial connection ?

Do I still need to upload a sketch on the arduino ?

Yes, to get started, I would develop the Arduino code and the wireless communication without Python. Just use input from the Serial monitor to develop your program. Changing the monitor input to input from a Python app will require few if any changes.

Documentation say it will be overruled by the Python code running.

The Python code is running on the computer, not the Arduino and it will not change the code on the the Arduino.

how do I tell the Arduino to send the message through the NRF once I've done the serial connection ?

Once the Arduino receives the serial message, you can just pass the received message to the nrf radio.

I would recommend a review of the Serial Input Basics tutorial.

1 Like

Thank you very much. I DID IT ! :grinning_face_with_smiling_eyes: :grinning_face_with_smiling_eyes:

Thanks to the Serial Input Basics tutorial and your advices, I managed to send my message using a Python code through the NRF modules, from one Arduino to another. Here's a little sum up of what I understood, if it can help other beginners :

  • The Arduino runs in full autonomy with its uploaded sketch, and cannot interact with data on your computer
  • You need to use a program to do so, using a programming language (here : Python)
  • The tool allowing the communication between the computer and the Arduino is the "Serial monitor" (available in the Arduino IDE : Tools/Serial Monitor)
  • The Python program will simulate the use of the Serial Monitor. The Arduino needs a downloaded sketch to use the data sent with the program
  • Once the program is running, everything happens in the program. If Python commands to write in the Serial Monitor, the only way to see the message is Python commanding to print what's on the Serial monitor. Every interaction must be in the same program
  • Basically use the code given in the Serial Input Basics Tutorial (previous answer) for your Arduino to deal with Serial Inputs.

Here 's my code, I think it can be helpful :

ArduinoUno = serial.Serial(port="COM3", baudrate=9600, bytesize=8, timeout=2, stopbits=serial.STOPBITS_ONE)
ArduinoNano = serial.Serial(port="COM4", baudrate=9600, bytesize=8, timeout=2, stopbits=serial.STOPBITS_ONE)

file = open('message.txt', 'r')
message = file.read() + '\n'
file.close()

bits = []

chaine = ''
for i in range(len(message)//8 + 1) :
        chaine = '' 
        chaine += message[8*i:8*i+8]
        bits.append(chaine)
print(bits)

while True : 
        for i in range(len(bits)):
                ArduinoUno.write(bytes(bits[i], 'utf-8'))
        time.sleep(1)
        print(ArduinoNano.read_all())

As you can see, I take my message in a txt file. I add '\n' because the downloaded sketch understands it as the end-of-line marker.

The maximum 'bytesize' length is 9. It will, therefore, cut every character further than the 8th position in a message sent to/from the serial monitor. Here's my syntax to end with the full original message, no matter its length.

For the question of the NRFs in particular, You can easily find a code to communicate with the NRFs on the web, and easily mix it with the codes in the Serial Input Basics tutorial. I'm not sure uploading these sketches, which are quite long though almost only literal copy/paste would be relevant, but do not hesitate to ask.

Thanks so much to everyone who took the time to answer me !
Archer

Hi,

Though the previous code does what I wanted to do (ie. sending a message in a txt file on my PC through radio modules connected to Arduinos), I have a strange output :

b'0110010010111000110101'
b'0110010010111000110101011001'
b'00101110001101010110010010111000110101'
b'0110010010111000110101'
b'0110010010111000110101'
b'0110010010111000110101'
b'0110010010111000110101'
b'0110010010111000110101'

The string you see in the first line is the one I want to send. It's correct. The ones after line 4 (included) are the same, and therefore correct. However, something messes up on lines 2 and 3. THere's actually 3 times the message on these 2 lines, one of the iteration being on both lines.

I don't understand, since the first line is correct and this mistake never returns after line 4. I ran this code 4 times now, and got the same output everytime (doesn't seem to be random). Do you have any idea, of where it can come from ?

Thank you,
Archer

You will need to post the code used on the Arduino and the Nano.

You must break your issue into smaller pieces.

Does the Arduino receive the correct message every time from the computer? Verify separately from the nrf sending to the Nano.

Does the Arduino send and the Nano receive, the correct message every time? Verify independently of python reading the Nano.

Does the Nano send the correct message to the computer and it is read correctly?

How do I do that ?

I tried changing few things either in the Arduinos code or in the Python code, but then it doesn't work. I can just tell the Uno receives the message correctly.

Here are the codes, the only part I dealt with are both loops and the "sendNewData" function in the Uno sketch :

*For the Uno (emitter) *

#include <SPI.h>
#include <RF24.h>

#define pinCE   7             // On associe la broche "CE" du NRF24L01 Ă  la sortie digitale D7 de l'arduino
#define pinCSN  8             // On associe la broche "CSN" du NRF24L01 Ă  la sortie digitale D8 de l'arduino
#define tunnel  "PIPE1"       // On définit un "nom de tunnel" (5 caractères), pour pouvoir communiquer d'un NRF24 à l'autre

RF24 radio(pinCE, pinCSN);    // Instanciation du NRF24L01

const byte adresse[6] = tunnel;               // Mise au format "byte array" du nom du tunnel
                    // Message à transmettre à l'autre NRF24 (32 caractères maxi, avec cette librairie)

const byte numChars = 32;
char receivedChars[numChars];   // an array to store the received data

boolean newData = false;

void setup() {
    Serial.begin(9600);
    Serial.println("<Arduino is ready>");
    radio.begin();                      // Initialisation du module NRF24
    radio.openWritingPipe(adresse);     // Ouverture du tunnel en ÉCRITURE, avec le "nom" qu'on lui a donné
    radio.setPALevel(RF24_PA_MIN);      // SĂ©lection d'un niveau "MINIMAL" pour communiquer (pas besoin d'une forte puissance, pour nos essais)
    radio.stopListening();              // ArrĂŞt de l'Ă©coute du NRF24 (signifiant qu'on va Ă©mettre, et non recevoir, ici)

}
void loop() {
    recvWithEndMarker();
    showNewData();
    sendNewData();
}

void recvWithEndMarker() {
    static byte ndx = 0;
    char endMarker = '\n';
    char rc;
    
    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (rc != endMarker) {
            receivedChars[ndx] = rc;
            ndx++;
            if (ndx >= numChars) {
                ndx = numChars - 1;
            }
        }
        else {
            receivedChars[ndx] = '\0'; // terminate the string
            ndx = 0;
            newData = true;
        }
    }
}

void showNewData() {
    if (newData == true) {
        Serial.print("This just in ... ");
        Serial.println(receivedChars);
        newData = false;
    }
}

void sendNewData() {
  if (newData == true){
    radio.write(&receivedChars, sizeof(receivedChars));     // Envoi de notre message
    delay(1000);   
  }
}

For the Nano (receiver)

#include <SPI.h>
#include <RF24.h>

#define pinCE   7             // On associe la broche "CE" du NRF24L01 Ă  la sortie digitale D7 de l'arduino
#define pinCSN  8             // On associe la broche "CSN" du NRF24L01 Ă  la sortie digitale D8 de l'arduino
#define tunnel  "PIPE1"       // On définit le "nom de tunnel" (5 caractères) à travers lequel on va recevoir les données de l'émetteur

RF24 radio(pinCE, pinCSN);    // Instanciation du NRF24L01

const byte adresse[6] = tunnel;       // Mise au format "byte array" du nom du tunnel  
char message[32];
boolean newData = false;
const byte numChars = 32;
char receivedChars[numChars];


void setup() {
  // Initialisation du port série (pour afficher les infos reçues, sur le "Moniteur Série" de l'IDE Arduino)
  Serial.begin(9600);
  Serial.println("RĂ©cepteur NRF24L01");
  Serial.println("");

  // Partie NRF24
  radio.begin();                      // Initialisation du module NRF24
  radio.openReadingPipe(0, adresse);  // Ouverture du tunnel en LECTURE, avec le "nom" qu'on lui a donné
  radio.setPALevel(RF24_PA_MIN);      // SĂ©lection d'un niveau "MINIMAL" pour communiquer (pas besoin d'une forte puissance, pour nos essais)
  radio.startListening();             // DĂ©marrage de l'Ă©coute du NRF24 (signifiant qu'on va recevoir, et non Ă©mettre quoi que ce soit, ici)
}

void loop() {
    recvWithEndMarker();
    showNewData();
    char message[32];
    if (radio.available()) {        // On vérifie si un message est en attente de lecture
     radio.read(&message, sizeof(message));// Si oui, on le charge dans la variable "message"
  }
}

void recvWithEndMarker() {
    static byte ndx = 0;
    char endMarker = '\n';
    char rc;
    
    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (rc != endMarker) {
            receivedChars[ndx] = rc;
            ndx++;
            if (ndx >= numChars) {
                ndx = numChars - 1;
            }
        }
        else {
            receivedChars[ndx] = '\0'; // terminate the string
            ndx = 0;
            newData = true;
        }
    }
}

void showNewData() {
    if (newData == true) {
        Serial.print("This just in ... ");
        Serial.println(receivedChars);
        newData = false;
    }
}