0

I'm currently trying to read serial data from an ESP8266 NodeMCU module to a Beaglebone Black. Essentially I trigger the NodeMCU to send a string via UART from the BBB and print the string to the BBB terminal. The following is the code on the BBB:

#include<iostream>
#include<fstream>
#include<string>
#include<unistd.h>
#include<termios.h>
#include<stdio.h>
#include<fcntl.h>
using namespace std;

int main(){
   std::fstream fs;

   // Setup UART
   int file, count;
   if ((file = open("/dev/ttyO4", O_RDWR | O_NOCTTY | O_NDELAY))<0){
      perror("UART: Failed to open the file.\n");
      return -1;
   }
   struct termios options; // the termios structure is vital
   tcgetattr(file, &options); // sets the parameters associated with file
   // Set up the communications options:
   // 115200 baud, 8-bit, enable receiver, no modem control lines
   options.c_cflag = B115200 | CS8 | CREAD | CLOCAL;
   options.c_iflag = IGNPAR | ICRNL; // ignore partity errors, CR -> newline
   tcflush(file, TCIFLUSH); // discard file information not transmitted
   tcsetattr(file, TCSANOW, &options); // changes occur immmediately

   fs.open("/sys/class/gpio/export");
   fs << "48";
   fs.close();
   fs.open("/sys/class/gpio/gpio48/direction");
   fs << "out";
   fs.close();
   fs.open("/sys/class/gpio/gpio48/value");
   fs << "1"; // "0" for off
   fs.close();
   usleep(1000000);
   fs.open("/sys/class/gpio/gpio48/value");
   fs << "0";
   fs.close();

   unsigned char receive[1000]; // declare a buffer for receiving data
   int characters = read(file, (void*)receive, 1000);
   if (characters == -1){ // receive the data
      perror("Failed to read from the input\n");
      return -1;
   }
   if (characters==0) printf("There was no data available to read!\n");
   else {
      receive[characters] = 0;
      printf("%s\n",receive);
   }
   close(file);

   return 0;
}

The following is the code on the NodeMCU:

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

  
  // Set D2 as input
  pinMode(4, INPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  if(digitalRead(4)==1){
    String msg = "Hola!";
    while(digitalRead(4)==1){
      
    }
    Serial.print(msg);
  }
}

When I run the C script, I get the following error:

Failed to read from the input
: Resource temporarily unavailable

However, I can open a Minicom terminal on the BBB on ttyO4 and the "Hola!" string gets printed once as expected.

How can I overcome this error?

  • Your termios initialization is low quality and incomplete. It might suffice for now with your trivial task. See [Setting Terminal Modes Properly](https://www.gnu.org/software/libc/manual/html_node/Setting-Modes.html) BTW Your program is not reading from the *"UART RX pin'*. Your Linux user program is several layers removed from the hardware, and *"reading"* means fetching bytes from the serial terminal buffer. – sawdust Dec 20 '21 at 01:39
  • @sawdust Right, that's a poor description of my question. My terminal only needs to read the buffer once per execution, so this probably will be enough, but my issue stemmed from not knowing how to set the terminal properties appropriately. I can't open the link you sent, do you have another resource I may browse? – Nolan Hermann Dec 20 '21 at 11:10
  • *"so this probably will be enough"* -- That translates to "I'm lazy, so I'm going to use a buggy program." See what happens when you simply try to read a longer message. The gnu.org site is back up, and the link is good. – sawdust Dec 20 '21 at 22:58

1 Answers1

1

Fixed it:

I inserted this line under the if statement that opens the ttyO4 port:

fcntl(file, F_SETFL, 0);

I also placed the Serial.print(msg); line in the NodeMCU code above the while loop.

  • You may think you *"fixed it"*, but do you understand the *"fix"*? – sawdust Dec 20 '21 at 01:33
  • @sawdust To a degree. I don't fully understand the parameters used in the "open()" and "fcntl()" calls, but I found that using "O_NDELAY" causes the terminal to read the buffer immediately, however without that line the BBB won't initialize the port without a voltage change over the serial line. The line in the answer removes the effect of the "O_NDELAY." – Nolan Hermann Dec 20 '21 at 11:16
  • That is almost cargo cult programming if you barely understand what functions & their parameters do and the reason for using them. In this case the difference is between non-blocking I/O versus blocking I/O. See https://stackoverflow.com/questions/25996171/linux-blocking-vs-non-blocking-serial-read/26006680#26006680. – sawdust Dec 20 '21 at 22:55