text:
Arduino EPROM dumper with utility program in C
I am writing EPROM dumper with Arduino UNO and utility program in C and I am using Ubuntu 20.04. The Arduino sketch works fine, but I am having few problems with the utility program. The first problem is that the utility hangs (like in some kind of infinite loop) if I don't open the serial monitor in Arduino IDE previously, or any other serial communication app (like puTTY). The second problem I have is that the utility also hangs when reading the last bytes which Arduino sends - inspecting the dumped file in hex editor, the last 4-6 bytes are missing. By printing string messages in the function serial_port_read_block_file, I think that the program hangs up in the read function.
Thank you in advance and sorry if I understood something wrong configuring the serial communication.
EDIT: Adding switch-case statement for setting the baud rate solved the first problem. The second problem is that I forgot that byte with the value of '\n' can be received, and I was just discarding this byte, so at the end I was missing few bytes. Also, I should have checked in the serial_port_read_block_file function if n>0, so I don't access address beyond the scope of the block array (with the statement buffer_cur_pos[-1], if n=0 I accessed invalid address).
Conclusion: As @Majenko suggested, I should implement some protocol that will wrap up the data transfer, to distinguish the data from the start/stop conditions. I also changed the code below with the fixes which made the program working (both, in the Arduino sketch and the utility program).
The Arduino sketch:
//74HC595 pins
const int shiftData = 10;
const int shiftClock = 11;
const int shiftLatch = 12;

//ROM data pins (successive)
const int romD0 = 2;

//pgm constants and variables
static const uint16_t BLOCK_SIZE = 256;
uint16_t nBytes = 0;
boolean readMode = false;

void sendAddress(uint16_t addr) {
  //first, send the high byte of the address
  shiftOut(shiftData, shiftClock, MSBFIRST, addr >> 8);
  //then, send the low byte of the address
  shiftOut(shiftData, shiftClock, MSBFIRST, addr);
  //pulse the shiftLatch pin, to output the address
  digitalWrite(shiftLatch, LOW);
  digitalWrite(shiftLatch, HIGH);
  digitalWrite(shiftLatch, LOW);
}

uint8_t readByte(uint16_t addr) {
  uint8_t data = 0;
  //send the address
  sendAddress(addr);
  for (int i = 7; i >= 0; i--)
    data = (data << 1) | digitalRead(romD0 + i);
  return data;
}

void sendBytes(uint16_t bytes) {
  //send the data in blocks with size BLOCK_SIZE
  const uint16_t BLOCKS = bytes / BLOCK_SIZE; //number of whole blocks
  const uint16_t REMAINDER = bytes % BLOCK_SIZE; //the remaining bytes that don't form a block

  uint8_t data[BLOCK_SIZE]; //buffer for block of bytes to be sent

  //send the whole blocks
  for (uint16_t block = 0; block < BLOCKS; block++) {
    for (uint16_t offset = 0; offset < BLOCK_SIZE; offset++) {
      data[offset] = readByte(block * BLOCK_SIZE + offset);
    }
    Serial.write(data, BLOCK_SIZE);
    delay(100);
  }

  //send the remaining bytes
  for (uint16_t offset = 0; offset < REMAINDER; offset++) {
    data[offset] = readByte(BLOCKS * BLOCK_SIZE + offset);
  }
  Serial.write(data, REMAINDER);
  Serial.write("\r\n"); //end of transmission
  delay(100);
}

void setup() {
  pinMode(shiftData, OUTPUT);
  pinMode(shiftClock, OUTPUT);
  pinMode(shiftLatch, OUTPUT);

  for (int i = 0; i < 8; i++)
    pinMode(romD0 + i, INPUT);

  Serial.begin(57600);

  //wait for serial port to connect
  while (!Serial) {}
}

void loop() {
  while (!Serial.available()) {} //wait until data is available
  char c = Serial.read();
  delay(100);
  switch (c) {
    case 'S': //send ready command
      Serial.write("> ");
    break;
    case 'R':
      readMode = true;
      while ((c = Serial.read()) != '\n') {
        nBytes = nBytes * 10 + (c - '0');
      }
      delay(100);
    break;
    default:
    break;
  }

  if (readMode) {
    sendBytes(nBytes);
  }

  //reset for next loop
  readMode = false;
  nBytes = 0;
  delay(100);
}

The utility program:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>

static const uint16_t BLOCK_SIZE = 256;
static const uint32_t BAUD_RATE = 57600;

void help(void) {
    printf(
            "rdump - ROM dumper\n"
            "usage: rdump [OPTIONS]\n"
            "Options:\n"
            "-p <serial port>       specify serial port of the Arduino\n"
            "-f <filename>          specify output filename\n"
            "-s <num bytes>         specify the number of bytes to read\n"
            "-h                     print this help file\n"
    );
}

//opening and initializing serial communication
int serial_port_init(const char *port, uint32_t baud) {

    //open serial port for read/write, save its file descriptor in fd
    int fd = open(port, O_RDWR | O_NOCTTY | O_SYNC);

    if(fd == -1) {
        fprintf(stderr, "serial_port_init: unable to open %s\n", port);
        return -1;
    }

    struct termios options; //serial port options

    //get the initial serial port options
    if(tcgetattr(fd, &options) < 0) {
        fprintf(stderr, "serial_port_init: unable to get terminal options\n");
        return -1;
    }

    //set the baud rate
    cfsetispeed(&options, (speed_t)baud);
    cfsetospeed(&options, (speed_t)baud);

    options.c_cflag |= (CLOCAL | CREAD); //enable the receiver and block control lines

    //set the character size to 8 bits, no parity bit and 1 stop bit (8N1 configuration)
    options.c_cflag &= ~PARENB; //no parity
    options.c_cflag &= ~CSTOPB; //1 stop bit
    options.c_cflag &= ~CSIZE; //bit mask for character size
    options.c_cflag |= CS8; //8 bit character size
    //disable hardware flow control
    options.c_cflag &= ~CRTSCTS;
    //configure for non-canonical mode
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHONL | ISIG); //disable cannonical mode, echo, erasure, new-line echo,  INTR, QUIT and SUSP
    options.c_iflag &= ~(IXON | IXOFF | IXANY); //disable software flow control
    options.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL); //disable any special handling of received bytes
    options.c_oflag &= ~OPOST; // prevent special interpretation of output bytes
    options.c_oflag &= ~ONLCR; // prevent conversion of newline to carriage return/line feed

    //read returns after 0.5 second timeout
    options.c_cc[VMIN] = 0;
    options.c_cc[VTIME] = 5;

    serial_port_flush(fd); //flush the serial port

    //set the new options for the serial port
    if(tcsetattr(fd, TCSANOW, &options) < 0) {
        fprintf(stderr, "serial_port_init: unable to set terminal options\n");
        return -1;
    }

    return fd;
}

//closing the serial communication
void serial_port_close(int fd) {
    close(fd);
}

void serial_port_flush(int fd) {
    sleep(2);
    tcflush(fd, TCIOFLUSH);
}

//check if serial port is ready
int serial_port_ready(int fd) {
    uint8_t c[1];
    uint8_t prev = 0;
    ssize_t n = read(fd, c, 1);
    int done = 0;
    if(n <= 0) return 0;
    prev = c[0];
    do {
        //printf("%02X", (uint8_t)prev);
        n = read(fd, c, 1);
        if(n <= 0) return 0;
        done = (prev == '>') && (c[0] == ' ');
        prev = c[0];
    } while(!done);
    return 1;
}

//writing to the serial port
ssize_t serial_port_write(int fd, const char *data) {
    size_t data_length = strlen(data);
    ssize_t n = write(fd, data, data_length);
    if(n != data_length) {
        fprintf(stderr, "serial_port_write: unable to write the data\n");
        return -1;
    }
    return n;
}

//reading block of bytes from the serial port into file
int32_t serial_port_read_block_file(int fd, uint8_t *block, uint16_t block_size, FILE **file) {
    uint8_t *block_cur_pos = block;
    memset(block, 0, block_size);

    ssize_t n;
    uint16_t total = 0;
    int done = 0;
    int try = 0;
    static const int TRIES = 5;
    //printf("serial_port_read_block_file: started reading block.\n");
    do {
        n = read(fd, block_cur_pos, block_size - (block_cur_pos - block));
        if(n == -1) {
            fprintf(stderr, "serial_port_read_block_file: unable to read the data\n");
            return -1;
        }
        block_cur_pos += n;
        total += n;
        //print_byte_array(block, block_cur_pos - block + 1);
        if(n > 0) {
            done = (block_cur_pos[-1] == '\n' && block_cur_pos[-2] == '\r') || (total == block_size);
        } else {
            try++;
            if(try >= TRIES) done = 1;
        }
    } while(!done);
    //printf("serial_port_read_block_file: done reading the required block. Total read: %u bytes\n", total);
    if(total == 0) return 0;
    if(block_cur_pos[-1] == '\n' && block_cur_pos[-2] == '\r') {
        total -= 2;
        fwrite(block, sizeof(uint8_t), total, *file);
    } else {
        fwrite(block, sizeof(uint8_t), total, *file);
    }
    fflush(*file);
    //printf("serial_port_read_block_file: done writing the bytes to the file.\n");
    return total;
}

//reading (bytes) bytes from the serial port into file
int32_t serial_port_read_file(int fd, FILE **file, uint16_t bytes) {
    uint8_t *block = (uint8_t*)malloc(BLOCK_SIZE * sizeof(uint8_t));
    uint16_t total = 0;
    ssize_t n;
    do {
        n = serial_port_read_block_file(fd, block, BLOCK_SIZE, file);
        if(n == -1) {
            return -1;
        }
        total += n;
    } while(total < bytes);
    free(block);
    //printf("Done reading.......\n");
    return total;
}

int main(int argc, char *argv[]) {
    char *port_name = NULL;
    char *file_name = NULL;
    uint16_t bytes;
    //parsing command line arguments
    opterr = 0;
    char c;
    while((c = getopt(argc, argv, "p:f:s:h")) != -1) {
        switch(c) {
            case 'p':
                port_name = strdup(optarg);
            break;
            case 'f':
                file_name = strdup(optarg);
            break;
            case 's':
                bytes = atoi(optarg);
            break;
            case 'h':
                help();
                return 0;
            break;
            default:
                fprintf(stderr,
                        "rdump: invalid option: %c\n"
                        "Try 'rdump -h' for more information.\n",
                        optopt);
                return 0;
            break;
        }
    }

    //opening serial port communication with the arduino
    int port = serial_port_init(port_name, BAUD_RATE);
    if(port < 0) {
        //fprintf(stderr, "rdump: unable to open port %s\n", port_name);
        free(port_name);
        free(file_name);
        return -1;
    }

    printf("rdump: serial communication to %s opened successfully\n", port_name);
    sleep(3); //wait for serial port to be ready

    //send command for testing if the serial port is ready
    char cmd[20];
    cmd[0] = 'S';
    cmd[1] = '\0';
    if(serial_port_write(port, cmd) < 0) {
        serial_port_close(port);
        return -3;
    }
    //check if serial port is ready
    if(!serial_port_ready(port)) {
        fprintf(stderr, "rdump: serial port is not ready.\n");
        serial_port_close(port);
        free(port_name);
        free(file_name);
        return -2;
    }
    printf("rdump: serial port is ready\n");
    //send command for reading n bytes
    sprintf(cmd, "R%d\n", bytes);
    if(serial_port_write(port, cmd) < 0) {
        serial_port_close(port);
        free(port_name);
        free(file_name);
        return -3;
    }
    //receive the requested data
    FILE *rom = fopen(file_name, "wb");
    fsync(fileno(rom));
    if(rom == NULL) {
        fprintf(stderr, "rdump: unable to create file %s\n", file_name);
        serial_port_close(port);
        free(port_name);
        free(file_name);
        return -4;
    }
    printf("rdump: file %s created successfully.\n", file_name);
    printf("Dumping ROM to file %s...\n", file_name);
    //uint8_t buffer[10000];
    //int n = serial_port_read_block_file(port, buffer, 10000, rom);
    //int n = serial_port_read(port, buffer, 10000);
    //fwrite(buffer, sizeof(uint8_t), n, rom);
    ssize_t dumped_bytes = serial_port_read_file(port, &rom, bytes);
    if(dumped_bytes < 0) {
        return -5;
    }
    if(dumped_bytes != bytes) {
        fprintf(stderr, "Dumped %zd of %u bytes\n", dumped_bytes, bytes);
    } else {
        printf("Done!\n");
    }
    //close the file, serial port and free the memory
    fclose(rom);
    serial_port_close(port);
    free(port_name);
    free(file_name);
    //printf("Exiting...\n");
    return 0;
}

For the baud rate on Linux you must use B57600 not 57600.

For your data transfer you should implement some form of protocol that wraps your data transfer and is distinguishable from your data transfer. One example would be to transfer the data as ASCII HEX with transfer start and stop markers that don't use 0-9A-F. One good example would be to implement Intel HEX format (the same format Arduino sketches are uploaded in) since that is a standard for EEPROM programmers to work with.

I've used https://github.com/Ghostbird/Arduino_EEPROM_RW in the past. Which is somewhat similar to what you are trying to do, as far as I can see.

@Majenko Thank you very much for your information. I thought that conversion from int to baud rate could be done just by casting the int to speed_t. Also I will try to implement protocol which you suggested.


text:
Playing stereo sound using AudioOutI2S and Splitting channels correctly
I have an Arduino MKR Zero with an UDA1334 I2S module, alongside 2 Speakers and I am trying to play Stereo sound. So far everything seems to work well, connections are also properly done, and i can play wav files. But i also want to be able to play sound either on the right channel only or sometimes only on the left channel. I tried to use audacity to make sounds only on the right channel for example, but when i play the .wav file, i still get the sound on both speakers. How can i fix this please? Is there any syntax to play sound only on the right channel? Thank you.
PS. TestR.wav is a only on the right channel.
#include <SD.h>
#include <ArduinoSound.h>

const char filename[] = "testR.wav";
SDWaveFile waveFile;

void setup() {
   Serial.begin(9600);
   while (!Serial){;};

   Serial.print("Initializing SD card...");
   if (!SD.begin(28)) {
    Serial.println("SD card initialization failed!");
    return;
  }
  Serial.println("SD card is valid.");
  waveFile = SDWaveFile(filename);   // create a SDWaveFile
//  Serial.println(typeof(waveFile));
 if (!waveFile) {
    Serial.println("wave file is invalid!");
    while (1); // do nothing
  }

// print out some info. about the wave file

Serial.print("Bits per sample = ");
Serial.println(waveFile.bitsPerSample());
long channels = waveFile.channels();
Serial.print("Channels = ");
Serial.println(channels);
long sampleRate = waveFile.sampleRate();
Serial.print("Sample rate = ");
Serial.print(sampleRate);
Serial.println(" Hz");
long duration = waveFile.duration();
Serial.print("Duration = ");
Serial.print(duration);
Serial.println(" seconds");

AudioOutI2S.volume(100);

 if (!AudioOutI2S.canPlay(waveFile)) {
    Serial.println("unable to play wave file using I2S!");
    while (1); // do nothing
  }
 Serial.println("starting playback");
  AudioOutI2S.play(waveFile);
}

void loop() {
  if (!AudioOutI2S.isPlaying()) {
    Serial.println("playback stopped");
    while (1);
  }
}

Can you at least, at the very minimum, post your code?

Sure, there you go! @Swedgin.

I went throught that library and I doens't seem like there is functionality to do what you want. channels() returns hardcoded 2 lol (I think that's the left and right channel). You'll have to write your own function to split the two. I don't know how SDWaveFile looks like (how the data is presented), so can't help you with that.

Thank you @Swedgin

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
I2C and softwareserial
Attempting to make gps unit with screen. GPS unit communicates over serial (Adafruit Ultimate GPS Breakout) and I can get GPS data through USB to my pc with Adafruit GPS library softwareserial examples. The screen communicates over I2C (Sunfounder OLED-SSD1306 Module) and I can get display with Adafruit SSD1306 examples. However I cannot get both to happen simultaneously. Board is Adafruit Metro Mini 5v 16MHZ. GPS is using pin 8 for TX and pin 9 for RX. Display is using A4 for SDA and A5 for SCL.
If "Adafruit_GPS GPS(&mySerial);" is not commented the screen will not display anything. If it is commented the screen displays just fine. How do I get both to function simultaneously?
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET     -1
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(8, 9);
Adafruit_GPS GPS(&mySerial);

void setup() {
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    for(;;);
  }
  display.display();
  delay(2000);
  display.clearDisplay();
  display.drawPixel(10, 10, SSD1306_WHITE);
  display.display();
  delay(2000);
  testdrawchar();
}

void loop() {
}

void testdrawchar(void) {
  display.clearDisplay();

  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.cp437(true);

  for(int16_t i=0; i<256; i++) {
    if(i == '\n') display.write(' ');
    else          display.write(i);
  }

  display.display();
  delay(2000);
}

I guess, you run out of memory

The problem was indeed running out of memory (as suggested by Juraj). After finding smaller libraries I was able to get it to work together just fine.

This is an incomplete answer. What libraries were chosen?

Final list of libraries:
#include <AltSoftSerial.h>   #include <TinyGPS.h>   #include <SoftwareSerial.h>   #include "SSD1306Ascii.h"   #include "SSD1306AsciiAvrI2c.h"   #include <Wire.h>
All of the Adafruit libraries were too large, so they all got switched out for more concise, compact libraries that fit my purposes

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
strcat gives error when I try to add a char to a char array
I have
char c;

where
int bt_available = Serial2.available();
if (bt_available) {
  c = Serial2.read();
}

and later in the code I try to
strcat(some_char_array, c);

and it gives me this error

initializing argument 2 of 'char* strcat(char*, const char*)' [-fpermissive]
  error: invalid conversion from 'char' to 'const char*' [-fpermissive]

My best guess why the error appears would be that strcat can only accept strings and char arrays, but not single characters, so a solution I can think of would be to create a char array like char test[1] where test[1] = '\0' and then test[0] = c but I'm not sure if that's the best way to go about the problem and if that's a solution. Does 'const char*' mean 'char[]'?
P.S I read Majenko's blog thingy and I'm turning all Strings to char arrays and it's a bit of suffering :P

A char is a single character. A char * and a char[] are both arrays of characters (more correctly char * is a pointer to an array of characters).
strcat expects two arrays or pointers to arrays of characters. If you want to add a single character you can either fool the compiler into thinking that the character is an array of characters of size 1 (but it lacks the required NULL termination) or manually manipulate the target array.
For the former you could use strncat and casting:
strcat(some_char_array, &c, 1);

That gives you a pointer to the character, which is as far as the compiler is concerned, indistinguishable to a pointer to an array of characters. You use the "n" variant of strcat  to limit it  to just one character (plus an added NULL character) so it doesn't rely on the missing NULL termination.
For the second you could do:
int n = strlen(some_char_array);
some_char_array[n] = c;
some_char_array[n+1] = 0;

That just sets the Nth character in the target array to whatever is in c, then adds a new NULL termination character to the end.


text:
How compile an Arduino program for a desktop PC
I have an arduino program that only does serial communications with a little bit of math, and I am writing another one to communicate with it on a second arduino.  For testing purposes I was hoping I could run the serial only program on my desktop.  I know it is possible to run on a raspberry pi but I have never done that.  Can I do something similar on windows?  If not, can anybody recommend the easiest way to do this with a regular C++ program that would require very little editing? Here is a copy of my code if it's helpful.  It basically increments a variable up and down between 0 and 100.
int pos = 60;
bool flag=0;
int dly=50;
int vel=0;

const int buttonPin =  12;      // the number of the LED pin

// variables will change:
int buttonState = 0;         // variable for reading the pushbutton status

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);

Serial.begin(115200);
}

void loop() {
    dly=50;
    buttonState = digitalRead(buttonPin);
    if (buttonState==0)dly=12;
    Serial.print(vel); //speed
    Serial.print(",");
    Serial.println(pos); //position
    delay(dly);
    if (pos==30)flag=1;
    if (flag==1) pos+=1;
    if (pos==100)flag=0;
    if (flag==0) pos-=1;
    vel=1000/dly;
    if (flag==0) vel*=-1;

}

try processing ... https://processing.org/ .... look for example sketches that do serial comm ...

I'm familiar with processing.  The goal for me is to just have one program that I can run in two places.  Otherwise I can just use python or another Arduino.

If you want to run the Arduino sketch on your desktop, you just have to
implement the Arduino core library for your PC.
It may not be as bad as it sounds. If your program makes only minimal
use of the Arduino core, you may implement only the parts you really
need. For example, this partial implementation is enough to run your
program:
#include <cstdint>
#include <iostream>
#include <unistd.h>  // for usleep()

using std::cout;
using std::endl;

#define INPUT_PULLUP 2

void pinMode(uint8_t, uint8_t) {}

uint8_t digitalRead(uint8_t) { return 0; }

void delay(int t) { usleep(t * 1000UL); }

struct {
    void begin(int) {}
    template<typename T> void print(T x) { cout << x; }
    template<typename T> void println(T x) { cout << x << endl; }
} Serial;

int main()
{
    void setup();
    void loop();
    setup();
    for (;;) loop();
}

I tested this on Linux, by simply appending your program right below
this. If you are using Windows, you will have to replace the usleep()
function with the appropriate Windows call (and <unistd.h> with the
appropriate header). The serial stream goes to the standard output. You
may redirect it to the USB serial port if you wish (trivial to do in
Linux, I assume it should be doable on Windows). You may also want to
replace digitalRead() with something that simulates a more realistic
user interaction.
Keep in mind that the sizes of the basic data types can be different on
the Arduino and on the PC. On an AVR-based Arduinos, int and pointers
are 16 bits while long is 32 bits. This is an “IP16” data model. An
ARM-based Arduino would typically be ILP32, whereas a 64-bit PC is LP64,
unless it runs Windows, in which case it's LLP64. This can make a
difference, especially if some of your calculations are prone to
overflow with the smaller data models.

Edit: I recently stumbled upon NCORE, a native core for
Arduino. It may be a good fit for what you are trying to do.
From the page description:

The native core allows you to compile and run Arduino sketches on the
  PC, generally with no modification. It provides native versions of
  standard Arduino functions, and a command-line interpreter to give
  inputs to your sketch that would normally come from the hardware
  itself.

This might be the way to go about it.  I'm just curious why all this is required for a desktop, but I can run an ino file on a raspberry pi without it.

@bobmcgrath: I guess someone has already implemented a quite complete Arduino-compatible core for the Raspberry... WiringPi maybe?

It depends on what exactly you wanna test. I guess you want to run the "Serial & math only" sketch on the PC, while communicating over Serial (via USB) with the other real Arduino. It can be done, but you would have to change quite a lot. The Serial libraries for a PC are different than for an Arduino. Also you cannot simply compile Arduino code for a PC, they are totally different devices.
Mostly the Serial code is better tested with the real hardware, by checking, what actually is send. You can do this by connecting to the Arduino over Serial/USB with a corresponding program (Arduino Serial Monitor, Putty, ...), so that you can test the functionality by hand. Or write a simple test sketch for the second Arduino.
For testing the math part, you could relatively easy write a so called unit test on the PC. A unit test tests a confined code part without or only with few dependencies. Most math is the same on Arduino and PC (as long as you use variables of the same size and type). So you could put all the math code into a function, which does not contain Arduino specific code, like Serial code. Just the math. Then you can copy that function into the source code of a C++ PC programm and use it, to test the math function unit without involving the Arduino.
A further option would be using an Arduino Simulator. But keep in mind, that these simulators can never be as good as the real hardware and you can see differences in the behavior of simulated and real Arduinos. Though it should work, as long as your program is simple and does not rely on too much outer hardware or events. Your current program is simple enough, so that a simulator should be able to work with it.
All in all: Testing your code outside of the real Arduino mostly only makes sense, when you have a complex program, that does not involve Arduino specific code, which would need the hardware to work. If your project is not very complex, you are mostly better off with testing directly with the real hardware.

There is also arduino_ci, a framework for running unit tests against an Arduino library (maybe also sketch) on your computer. It contains mock implementations of most Arduino functions and some libraries, and gives the unittest control of things like Serial buffers and I/O pin values.
For your example, you could maybe write a unittest that just use stdin/stdout as a serial port and then connect two of these programs together, or maybe you could generalize your communication code a bit into an object and then instantiate that twice.


text:
Problem with if condition
So my project is including detecting the temperature in the room by using dth11 sensor.
my idea is to add 3 LED lights were each light represent the temperature if its cold or hot or perfect.
the wiring and coding is done and it's working .However, i'm having a problem were the perfect temperature is always on no matter if the temperature is hot or cold.
example: if the temperature is cold the cold LED will blink and the perfect temperature LED will be on.
#include <Adafruit_Sensor.h>
#include <DHT.h>
#define DHTPIN A0
#define DHTTYPE DHT11
#define LED_TOO_COLD 6
#define LED_PERFECT 8
#define LED_TOO_HOT 7
DHT dht(DHTPIN, DHTTYPE);
void setup() {
  Serial.begin(9600);
  Serial.println("DHT11 test!");

  dht.begin();
}

void loop() {

  pinMode (6 , OUTPUT);
  pinMode (7 , OUTPUT);
  pinMode (8 , OUTPUT);
  delay(2000);

  float h = dht.readHumidity();
  float t = dht.readTemperature();
  float f = dht.readTemperature(true);

  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  Serial.print("Humidity: ");
  Serial.print(h);
  Serial.print(" %\t");
  Serial.print("Temperature: ");
  Serial.print(t);
  Serial.println(" *C ");
  if (t < 22) {
    Serial.println("Too cold!");
    digitalWrite(6, HIGH);
    digitalWrite(7, LOW);
    digitalWrite(8, LOW);
    delay (2000);
  }
   if (t >26) {
    Serial.println("Too hot!");
    digitalWrite(7, HIGH);
    digitalWrite(6, LOW);
    digitalWrite(8, LOW);
    delay (2000);

  } else {
    Serial.println("Perfect temperature!");
    digitalWrite(8, HIGH);
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
    delay (2000);
  }

}

firstly, move your pinMode() settings to setup section.
in your code, when the temperature is 21 active pin will be 6 and 8.
you should rewrite your code in next ways:
1:
if (t < 22) {
  ... its cold temp ...
} else if (t > 26) {
  ... its hot temp ...
} else {
  ... it's nor temp ...
}

2:
if (t < 22) {
   ... its cold temp ...
}
if (t > 26) {
   ... it's hot temp ...
}
if (t >= 22 && t <= 26) {
   ... it's nor temp ...
}

and my small advice for u, rewrite in this way, it is more readable
digitalWrite(6, HIGH);
digitalWrite(7, LOW);
digitalWrite(8, LOW);

digitalWrite(6, LOW);
digitalWrite(7, HIGH);
digitalWrite(8, LOW);

digitalWrite(6, LOW);
digitalWrite(7, LOW);
digitalWrite(8, HIGH);

visually changing ENUMS (like LOW or HIGH) more noticeable than changing numbers (6/7/8)


text:
Better version of MPU6050
I need really good gyroscope for my quadcopter and now I have MPU6050. I don't like how it works, after some time of use, data is absolutely wrong. So I need good gyroscope, could you pls advice the best gyroscope for Arduino?

"after some time of use, data is absolutely wrong" - That sounds like you are using the raw data, which is always problematic. The different data outputs have to be combined through means of sensor fusion. How are you using the data from the MPU?

use this: https://howtomechatronics.com/tutorials/arduino/arduino-and-mpu6050-accelerometer-and-gyroscope-tutorial/ . I attached image where I just do nothing.

You want a better gyroscope? Here's one. You want a MEMS gyroscope? They're all pretty much the same, and all respond in the same way. It's your job to deal with the data in the right way.

is it explains why all sketches from internet give the same bad behavior?

You should read this: https://www.analog.com/en/analog-dialogue/raqs/raq-issue-139.html and you will then understand what you ask is an impossibility.

To be honest, I really don't see why the values are that bad. Please explain more about how they are wrong. They seems to mainly change behind the decimal point. The typical flight controller in a quadcopter also uses a similar MPU, though it also uses more different sensors for the sensor fusion, that improves the quality

@chrisl, I expect right values, like 90 degree when it is vertical and so on. May be I should use only changes of values but not values?


text:
Arduino SIM900 No SMS received
I tried the tutorial in this link
https://lastminuteengineers.com/sim900-gsm-shield-arduino-tutorial/
to send an SMS message using a SIM900 GSM shield
I completed the section to send AT commands successfully but I can't get
the Arduino Uno to send an SMS. Below is the output I get after doing AT command tests
Initializing...
AT

OK
AT+CPIN?

+CPIN: READY

OK
AT+CSQ

+CSQ: 6,0

OK
AT+CCID

8944500105191448516F

OK
AT+CREG?

+CREG: 0,5

OK
AT+COPS?

+COPS: 0,0,"T-Mobile "

OK
AT+COPS=?

+COPS: (2,"T-Mobile ","T-Mobile ","310260"),,(0,1,4),(0,1,2)

OK

and below are the responses from the SMS code
Initializing...
AT

OK
AT+CMGF=1

OK
AT+CMGS="+1mycellphonenumber"

> Last Minute Engineers | lastminuteengineers.com

so no response from the AT+CMGS command and NO SMS received.
Plug is 5V 2A.
Any idea what might be causing the issue?
Below is the code I used for the Setup() function
void setup()
{
  //Begin serial communication with Arduino and Arduino IDE (Serial Monitor)
  Serial.begin(9600);

  //Begin serial communication with Arduino and SIM900
  mySerial.begin(9600);

  Serial.println("Initializing...");
  delay(1000);

  mySerial.println("AT"); //Handshaking with SIM900
  updateSerial();

  mySerial.println("AT+CMGF=1"); // Configuring TEXT mode
  updateSerial();
  mySerial.println("AT+CMGS=\"+ZZxxxxxxxxxx\"");//change ZZ with country code and xxxxxxxxxxx with phone number to sms
  updateSerial();
  mySerial.print("Last Minute Engineers | lastminuteengineers.com"); //text content
  updateSerial();
  mySerial.write(26);
}

Changed my SIM card to Ting from Hologram and it worked just fine!

It's OK to accept your own answer as the solution to the problem.

Normally in Setup() you have in the end this sequence
Serial.println("Connecting to the network...");

while( (sendATcommand("AT+CREG?", "+CREG: 0,1", 500) ||
    sendATcommand("AT+CREG?", "+CREG: 0,5", 500)) == 0 );

     sprintf(aux_str, "ATD%s;", phone_number);
     sendATcommand(aux_str, "OK", 10000);

     delay(seconds * 1000);

    Serial.println("ATH"); // disconnects the existing call

So after the registering you send
 Serial.println("AT+CMGS=\"1234567890\""); //CHANGE TO DESTINATION NUMBER

Did you use the \" for the embracing the number. Without your real command its hard to guess. Better use a test program Soft Serial GPRS Code, serial monitor is error prone.
EDIT The OP posted code parts. The code after:
  Serial.println("Initializing...");
  delay(1000);

should be in the loop()- Look at the linked examples how should communication take place if the code is run once so no recurring tasks like reading chars or similar.

I posted the Setup() function code I used above, the line below is to send the SMS. mySerial.println("AT+CMGS="+1mycellphonenumber"");


text:
Please help me combine the two codes for DHT11 and SW-420 Vibration sensor for arduino in one program
The following is the code used for DHT11 Temperature and Humidity sensor:
#include <LiquidCrystal.h>
LiquidCrystal lcd(4, 5, 0, 1, 2, 3);
byte degree_symbol[8] =
              {
                0b00111,
                0b00101,
                0b00111,
                0b00000,
                0b00000,
                0b00000,
                0b00000,
                0b00000
              };
int gate=11;
volatile unsigned long duration=0;
unsigned char i[5];
unsigned int j[40];
unsigned char value=0;
unsigned answer=0;
int z=0;
int b=1;
void setup()
{

lcd.begin(16, 2);
 lcd.print("Temp = ");
 lcd.setCursor(0,1);
 lcd.print("Humidity = ");
 lcd.createChar(1, degree_symbol);
 lcd.setCursor(9,0);
 lcd.write(1);
 lcd.print("C");
 lcd.setCursor(13,1);
 lcd.print("%");
}

void loop()
{

 delay(1000);
 while(1)
 {
  delay(1000);
  pinMode(gate,OUTPUT);
  digitalWrite(gate,LOW);
  delay(20);
  digitalWrite(gate,HIGH);
  pinMode(gate,INPUT_PULLUP);//by default it will become high due to internal pull up
 // delayMicroseconds(40);

  duration=pulseIn(gate, LOW);
  if(duration <= 84 && duration >= 72)
  {
      while(1)
      {
        duration=pulseIn(gate, HIGH);

        if(duration <= 26 && duration >= 20){
        value=0;}

        else if(duration <= 74 && duration >= 65){
        value=1;}

        else if(z==40){
        break;}

        i[z/8]|=value<<(7- (z%8));
        j[z]=value;
        z++;
      }
    }
answer=i[0]+i[1]+i[2]+i[3];

if(answer==i[4] && answer!=0)
{
lcd.setCursor(7,0);
lcd.print(i[2]);
lcd.setCursor(11,1);
lcd.print(i[0]);
}

z=0;
i[0]=i[1]=i[2]=i[3]=i[4]=0;
 }
}

The following is the code for SW-420 Sensor:
int LED_Pin = 13;
int vibr_Pin =3;

void setup(){
  pinMode(LED_Pin, OUTPUT);
  pinMode(vibr_Pin, INPUT); //set vibr_Pin input for measurment
  Serial.begin(9600); //init serial 9600
 // Serial.println("----------------------Vibration demo------------------------");
}
void loop(){
  long measurement =TP_init();
  delay(50);
 // Serial.print("measurment = ");
  Serial.println(measurement);
  if (measurement > 1000){
    digitalWrite(LED_Pin, HIGH);
  }
  else{
    digitalWrite(LED_Pin, LOW);
  }
}

long TP_init(){
  delay(10);
  long measurement=pulseIn (vibr_Pin, HIGH);  //wait for the pin to get HIGH and returns measurement
  return measurement;
}

Assuming the DHT11 Pin configuration remains unchanged and you can change the pin configurations for SW-420 vibration sensor, please give me a combined code for the two sensors to display results in one program. Thanks a lot.

Hello and welcome to Arduino! Please take the tour and visit the helpcenter to see how things work here.

Have you already tried combining those sketches? If yes, what's the problem you actually have? If no, try it. We are not supposed to do the job for you but we'll guide you to the solution.

There are multiple threads on how to combine two different sketches. One of the main things you have to do is refactor your code to get rid of calls to delay(). Do a Google search on Arduino blink without delay and read one of the tutorials you find. The idea is to make a call to the millis() function for each thing you want to do on a time intervl, save the current millis count, and then wait until the new value of millis() is greater than the saved value by your desired time interval. By doing that, your code does a very fast series of checks:
"is it time to do <thing 1> again?"
"Is it time to to <thing 2> again?"
"What about <thing 3>"
And repeats.
Then it doesn't freeze the rest of your sketch waiting for time to pass. (That is what delay() does. Everything stops until the delay time has passed, which is bad.)


text:
Doubt using character array
I'm trying to make a led sign with a WS2812b ledstrip, using the FastLed library (by the way, this is a great library!), I'm already able to show a text (so far only one, which I leave saved in an array of characters at the beginning of the program), but I would like to be able to change this text using the serial port of the Arduino, and here is the problem:
When setting the text to be displayed in the array of LEDs, the function that I should use is:
ScrollingMsg.SetText ((unsigned char *) TxtDemo, sizeof (TxtDemo) - 1);}

Where TxtDemo is a variable type char array.
Until here all is right, as I commented I can show the text, but at the time of receiving the data from the serial port and save them in the char array TxtDemo, when I use the function sizeof(TxtDemo), the value I get remains with the original size (quite understandable) of this array.
For example: If the initial text was (saved in TxtDemo):
"Hello world", the sizeof() function, returns "11",
But when I pick up what I want to show on the serial port and store it in the variable TxtDemo, there's no way I can alter the size of that array. So ... what can I do? What do you recommend me to do?

Arrays in C are fixed. sizeof() will always give the amount of allocated memory for the array.
Instead, you should be using strlen() to get the number of characters up to (but not including) the terminating NULL character at the end of the string.
ScrollingMsg.SetText ((unsigned char *) TxtDemo, strlen(TxtDemo));

Make sure that you have enough space in your initial array to store the longest string you will want to send - it will not grow beyond your initial allocation. Also be sure to get the NULL character at the end of your valid text. It's too easy to forget you need to insert that after your last received character.

Thanks for the quick answer... now: how can add the null character???

I do it while reading from serial. For every character I place in the array I set the next entry to 0. Here's an example: https://majenko.co.uk/blog/reading-serial-arduino

Men... that article is, just, GREAT!!!! Thanks!!!

@k.Cyborg You might find this useful too: https://majenko.co.uk/blog/arrays-pointers-what-c


text:
Is it correct to use a 9V 1A transformer to power my project?
I have a quick question:
I have a small alarm project running on an ArduinoNanoV3 (a chinese clon). Counting sensors, actuators and the arduino itself the consumed current (theoretically speaking, calculated by the data provided by the datasheets) doesn't approach to a max of 300mA. Now, the way I plan to feed the project is using a 110V (AC) transformer that gives me 9V output with 1A maximum output. My fear is the output of this transformer (that says 1A) when in all places recommend not to use sources that give currents greater than 500mA when you are going to feed it by the pin VIn with 9V.
My question is: if my project is not going to consume more than 300mA, is there any danger/trouble when connecting the 9V ~ 1A transformer for energize my Arduino based project?

in all places recommend not to use sources that give currents greater than 500mA when you are going to feed it by the pin VIn with 9V.

Nowhere says that.  They say you should not draw more than 500mA when you supply with 9V.
The heat generated by the 5V voltage regulator is proportional to the current multiplied by the voltage.  The more current you draw the hotter the regulator will get. The higher the input voltage, the more voltage it has to drop, and thus the hotter it gets.
So the higher the input voltage the lower the current drawn by your project can be before the regulator gets too hot.
Since you are only around 300mA that's below the recommended maximum for a 9V input.

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/


text:
How to connect/call to the PSTN network using Arduino?
For a few months I made an alarm for my house, it is very simple: it is based on magnetic sensors DC-1561 (for windows and exterior doors), a few PIR sensors for rooms, buttons, LEDs and (of course) an ArduinoNano v3. Something simple!
The question is that lately I do not spend much time in my house and I would like it when I'm away from home the alarm calls me (when is activated) to my cell phone using the public switched telephone network (PSTN) because I live in Cuba and it's the easiest way and cheaper (the GSM modems/modules are very expensive for me). I do not want to leave any message or sound record, just call me and receive the call on my cell phone, using the RJ-11 connector (in my country only 2 pins are used) to connect it with the Arduino/some_IC.
I have been investigating since yesterday and have found quite a bit of information. The most recommended/successful that I found (remember that I want to continue using the system that I already have, I just want to add to the Arduino the ability to use the mark through the PSTN) is to use an IC (HT9200B) that is a generator of DTMF codes (as see in the figure) with serial AND parallel connection, aparently, compatible with the electronic logic of the Arduino (5V).

But of all the information that I found is to connect to this IC (HT9200B) a speaker and reproduce the DTMF codes. This is not what I want, what I want is to connect directly to the phone line and be able to "call" from it.
Anyone have any ideas, links, projects in progress, or anything that can help me?

You need an FXO device. The simplest of these is a MODEM.

@Majenko Anyone in particular? Have you work with one that you can recommend to me?

They are hard to find new now. You want an external MODEM (RS232 one - find one on eBay) and a UART to RS232 (e.g., MAX232 based) adaptor.

https://www.ebay.com/sch/i.html?_nkw=external+modem+rs232

Mmm... Ok, let's assume that I already buy the modem and the UART to RS232 adaptor, now: how can I use it with Arduino?

You connect the TX of the Arduino through the adaptor to the RX of the modem, and the other way around as well. Then send something like "ATDT18005553827\n" at the right baud rate. Wait 10 seconds or so, then send "\n" to cancel the call.

It's something like the SIM900, a GSM modem that work with 2g and GPRS (work flawlessly in my country), with the AT commands? Let me do some research, when I found one that I think I could use, can I consultate with you?

It's the predecessor. It uses the "Hayes" AT command set that GSM modems later on inherited.

Somethink like this one would work for me: modem ?

Sure. Looks good to me. Any one will do. They all work the same.

As already written in the comments, you may use any RS232 modem you can find. They use the so-called AT commands, which is a very common way to exchange commands with this kind of peripheral. You can check on wikipedia or on google to get more information on it.
The main problem is that this kind of modems are a bit hard to find (or at least, they are a bit harder to find and a bit too expensive for my liking). That's why, for a project of mine, I wanted to switch to a cheaper alternative. Looking on the internet, a lot of people stated that it was much better to have an already approved instrument rather than designing your own. For this reason, I bought a mini-phone like this one:

You just have to open it, wire the keys (or rather, the rows and columns of the keypad) to the arduino and let it do the magic.
This solution is cheaper (I spent 4€ for this, but if you have an old phone it becomes free) than getting a RS232 modem, but needs more work on your side.

I like your solution more. Could you give me the link where you bought the phone that you show me in the image? When I search (Amazon, eBay and Aliexpress) I get many cell phones and landlines, and I would like to buy yours, because I know it works. Thanks for the advice!

Is this one?

I bought it from ebay, but it is the same as yours. Just note that I did not complete the project, and with respect to the modem this requires you to tinker with it a bit more. On the other side you will technically be able to send also audio and receive DTMF codes

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/


text:
ESP32 millis not working properly
I have a program which measures temperatures every 30 minutes and sends them to a database. Immediately after running the program the first measurement is sent, however, the second (which should be sent after 30 min), is sent only after 1 hour. From then on the code works fine. The time is measured in millis. However, if I set the time difference to 28 minutes everything works fine from the beginning. What could be the reason for this? Is there a possibility that it goes to sleep mode? I don't understand why it works fine with 28 minutes and it stops working with 29 minutes?
Thanks in advance!
My code:
if (millis() - sendDataPrevMillis > 1740000)
  {
    sendDataPrevMillis = millis();

//other code

}

The only part I change, so it works is setting millis from 1740000 (29 minutes) to 1680000 (28 minutes).

Share your code with us.

Please provide a minimal compilable example code, that shows your problem, not just a super small code snippet

use unsigned long as data type of sendDataPrevMillis

Did you make sure that millis() returns 0 at startup? For debugging you could print the initial value and any following if the condition is met.

Although not strictly required, maybe use parentheses around millis() - sendDataPrevMillis for readability;
I guess you will have initialised sendDataPrevMillis to 0 but
the first time you assign sendDataPrevMillis to millis() some time will have elapsed since you evaluated. So calling millis() twice will give different results. That makes it less easy to see what is going on.

Suggestion to try:
long HALFHOUR = 30 * 60 * 1000L;

if ( (millis() % HALFHOUR ) == 0L ) {
    //measure and send
    //....
}

Hope this helps.
NB: % is what is called the 'modulo operator' see: https://www.geeksforgeeks.org/modulo-operator-in-c-cpp-with-examples/

I don't quite understand, what you mean with your second point. Calling millis() multiple times will give different results, when between the calls at least one millisecond passed. When initializing sendDataPrevMillis to zero, the time will be counted from startup (power cycle or reset). It is not very probable, that the code has run over half an hour before reaching the if statement the first time. So why should that matter?

The prob. of that will of course be very small indeed. what I was trying to say was about style: when the condition of the loop refers to the actual progressed millis (the first call) I would suggest to store exactly that value. Assignment within the condition
if ( (currentMillis = millis()) - sendDataPrevMillis > 1740000) {
sendDataPrevMillis = currentMillis;
in order to prevent that becomes a bit messy, don't you think?

You can do that with the assigment in if condition, but I don't think that this is better readable. Though that is subjective. In your second point you don't talk about style. As I now understand you say, that the millis() calls in the if condition and in the following inner statement give different results. I don't think that. The code runs way too fast for  that. Even if the code happens to accidentally hit the exact point, where millis() increments, that will mean a max error of 1ms. Not important, when in this time range and also when you are using millis().

what are the odds of hitting that at the exact ms out of thousands?

This has too much potential to go wrong in a real time environment and isn't better code than the one in the question. Besides, timers that depend  on millis() should always be unsigned long (or uint32_t).


text:
Reset a UART connection on a Due
I have a system that involves an Arduino Due connected to a Raspi 4 through UART in which the Due sends a heartbeat signal over UART for the pi to receive and send back as confirmation. One of the events that I need to handle is re-establishing the UART connection between the two devices if the program receiving UART on the pi (or the pi itself) fails for any reason and reboots. At the moment, I have the initial heartbeat working (as long as the pi program starts first) but when I stop the pi program to simulate a fatal error and restart it, the Due doesn't seem to receive heartbeat confirmation until it's reset as well.
Is there a clean way to reset just the one Serial connection from the Arduino script? I thought of using Serial.end() and Serial.begin() but that's really ugly and I'd prefer to avoid it. None of the other Serial library methods seem to provide the ability to reset the connection.
I'm using Serial2 at 115200 baud.
Edit: Including relevant heartbeat code:
#include <DueTimer.h>

bool heartbeat = true;

void rx_heartbeat() {
  int received_data;

  if (Serial2.available() > 0) {
    received_data = Serial2.read();
    heartbeat = true;
    Serial.println("beat");
  }
}

void setup() {
  Serial2.begin(115200);
  Timer1.attachInterrupt(heartbeat_ISR).setFrequency(1).start();
}

void loop() {
  rx_heartbeat();
}

void heartbeat_ISR() {
  if (heartbeat) {
    heartbeat = false;
  } else {
    // no heartbeat returned - stop normal operation
  }
  Serial.println("heart");
  Serial2.write(255);
}

You want to reset the connection, that is to turn it off and back on again.  Why do you think end and then begin isn't a good solution for that?  What's ugly about it?

why do you need to use 115200 baud for a heartbeat?

@Delta_G I could be approaching it very wrong, but the way I was thinking of implementing them would mean that both Serial.end() and Serial.begin() would be executed with every loop iteration. It just seems messy.

@jsotola it's definitely not necessary to have that high of a baud for a heartbeat. It's just my default rate I set for serial connections in general

Why would you do it every loop?  Does the communication need to be reset every loop?  Just reset it when needed, like when you stop getting your heartbeat.

Silly me forgot to actually upload the code that fixed my issue. The code shown in the question is correct and works as intended.


text:
Nextion Display won't show data
I'm prototyping my Weather Station on Wemos D1 mini pro (ESP8266) with BME280 sensor and Nextion Display. The problem is that my display doesn't show data from the sensor and from the internet (openweathermap.org), it's only showing the static numbers which I assigned in Nextion Editor.
Here's my code (I hid the ssid, password, apikey and CityID):
#include "Wire.h"
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
#include "SparkFunBME280.h"
BME280 mySensor;
float hums;
float temps;
float pres;

float tempitod;
float humitod;
float pressitod;
String data;
String result;

char ssid[] = "";
char pass[] = "";
String APIKEY = "";
String CityID = "";

WiFiClient client;
char servername[] = "api.openweathermap.org";

void setup() {
  Serial.begin(9600);
  Serial.print("restart");
  Wire.begin();
  Wire.setClock(400000);
  mySensor.setI2CAddress(0x76);
  mySensor.beginI2C();
  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
}

void loop() {
  hums = mySensor.readFloatHumidity();
  temps = mySensor.readTempC();
  pres = mySensor.readFloatPressure();
  getWeatherData();
  NextionData();
  Serial.print("Humidity: ");
  Serial.print(hums, 2);
  Serial.print(" Temp: ");
  Serial.print(temps, 2);
  Serial.print(" Pressure: ");
  Serial.print(pres, 2);
  Serial.println();
  delay(3000);
  }

void getWeatherData()
{
  if (client.connect(servername, 80)) {
    client.println("GET /data/2.5/weather?id=" + CityID + "&units=metric&APPID=" + APIKEY);
    client.println("Host: api.openweathermap.org");
    client.println("User-Agent: ArduinoWiFi/1.1");
    client.println("Connection: close");
    client.println();
  }
  while (client.connected() && !client.available()) delay(1);
  while (client.connected() || client.available()) {
    char c = client.read();
    result = result + c;
  }
  client.stop();
  result.replace('[', ' ');
  result.replace(']', ' ');
  char jsonArray [result.length() + 1];
  result.toCharArray(jsonArray, sizeof(jsonArray));
  jsonArray[result.length() + 1] = '\0';
  StaticJsonBuffer<1024> json_buf;
  JsonObject &root = json_buf.parseObject(jsonArray);
  String location = root["name"];
  String country = root["sys"]["country"];
  float temperature = root["main"]["temp"];
  float humidity = root["main"]["humidity"];
  String weather = root["weather"]["main"];
  String description = root["weather"]["description"];
  float pressure = root["main"]["pressure"];
  Serial.println(temperature);
  Serial.println(humidity);
  Serial.println(pressure);

  tempitod = temperature;
  humitod = humidity;
  pressitod = pressure;
}

void NextionData() {
  data = "tempitod.txt=\"" + String(tempitod, 1) + "\"";
  Serial.print(data);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
  delay(500);
  data = "humitod.txt=\"" + String(humitod, 1) + "\"";
  Serial.print(data);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
  delay(500);
  data = "pressitod.txt=\"" + String(pressitod, 1) + "\"";
  Serial.print(data);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
  delay(500);
  data = "temps.txt=\"" + String(temps, 1) + "\"";
  Serial.print(data);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
  delay(500);
  data = "hums.txt=\"" + String(hums, 1) + "\"";
  Serial.print(data);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
  delay(500);
  data = "pres.txt=\"" + String(pres, 1) + "\"";
  Serial.print(data);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
  delay(500);
}

The screen seems to be working fine, but it but doesn't gather data from the Wemos (and BME280). Could the problem be with bauds? I set the bauds in my code for 9600 but I don't know whether it changes anything. The strangest part is that, the debugger in Nextion Editor shows correct measurements.
Nxtion display looks like this right now (it doesn't gather data)

And the view from debugger looks like this (it gathers data correctly from the internet and BME280 sensor):

I don't know why Nextion doesn't display measurements.
Here's also photo from connecting Nextion to Wemos D1 mini. Maybe something is bad connected?:

I connected D7 pin from Wemos to RX on Nextion, and D4 pin from Wemos to TX on Nextion.

In NextionData() you appear to be writing Nextion commands using Serial. How is that possibly going to work?

@romkey It's a modified code from GreatScott: https://www.youtube.com/watch?v=daS2CE-zFNo&t=478s
He uses exactly the same Wemos and Nextion. I thought it would work as good as he did. What should be there instead of "Serial"?

Why do you think Serial will communicate with the Nextion when you've connected the Nextion on D7 and D4, which are not the serial port lines?


text:
printing data from gps on Serial1 and sensors into Serial
I am having some trouble using my gps (on Serial1) with my other sensors.
They both work great independently but when I use them in the same code, it's either the gps or the sensors that get to write on the Serial monitor.
For my gps I am using TinyGPS++, but I have a feeling that's not what's causing this problem here.
To simplify the code I'll be replacing what the sensors are supposed to write with this:
Serial.println("Hello there");

Here is the code
  if (Serial1.available() > 0) {
    gps.encode(Serial1.read());
    if (gps.location.isUpdated()){
      Serial.println("Satellite Count:");
      Serial.println(gps.satellites.value());
      Serial.println("Latitude:");
      Serial.println(gps.location.lat(), 6);
      Serial.println("Longitude:");
      Serial.println(gps.location.lng(), 6);
      Serial.println("Speed KT:");
      Serial.println(gps.speed.knots());
      Serial.println("Altitude Feet:");
      Serial.println(gps.altitude.feet());
      Serial.println("");
    }
  }
  Serial.println("Hello there");

I get this
Hello there
Hello there
Hello there
Hello there
Hello there
Hello there
Hello there
Hello there
Hello there
Hello there
Hello there
Hello there
Hello there
Hello there

If the line is removed, I get this
Satellite Count:
5
Latitude:
xx.xxxxx
Longitude:
-xx.xxxxxx
Speed KT:
0.19
Altitude Feet:
331.69

Thank you

add the sketch to the question? the GPS library returns data only if it is collected while your print in loop is executed in every loop

@Juraj excuse me, I don't understand. Can you please say again in other words ?

print a timestamp inside the if block ... add serial.println ( millis() ); before "Satellite Count:" .... add one also at "Hello there"

@jsotola I changed it to text. My timestamp is actually just the number of seconds since 01 Jan 1970, like this

thank you for removing the pictures, now the program listing is legible .... you are missing the point about the millis() ... print the value of millis() and examine the result .... how often does loop() repeat? ...  how often does if (gps.location.isUpdated()){ repeat?

both repeat to infinity

it looks like my issue is similar to this one https://arduino.stackexchange.com/questions/70269/my-gps-coordinate-does-not-show-only-my-ultrasonic-output-came-out

This looks like another case of serial spam.  I recommend changing to a frame-based approach and controlling that rate with checks to millis.
That limits the spam.  Alternative is to limit it outright to 1:
//a static global:
static int isaidHELLO = 0;

//later in the loop
if (Serial1.available() > 0) {
    gps.encode(Serial1.read());
    if (gps.location.isUpdated()){
      Serial.println("Satellite Count:");
      Serial.println(gps.satellites.value());
      Serial.println("Latitude:");
      Serial.println(gps.location.lat(), 6);
      Serial.println("Longitude:");
      Serial.println(gps.location.lng(), 6);
      Serial.println("Speed KT:");
      Serial.println(gps.speed.knots());
      Serial.println("Altitude Feet:");
      Serial.println(gps.altitude.feet());
      Serial.println("");
      isaidHELLO = 0;
    }
  }
  if(isaidHELLO == 0)
  {
      Serial.println("Hello there");
      isaidHELLO = 1;
  }

Thank you this works great !


text:
What is the name of a peripheral which reads servo output data physically?
I know the title is phrased terribly, but I'm not sure how to phrase it since I'm not sure of the name.
I have a servo, that I cannot connect to, except for the output spine/shaft (physically).  I need to get the output of that servo into an arduino, or raspberry pi.  So I need some kind of peripheral that can attach to the shaft of the servo, and tell me what position it's in.  I can't figure out how to find what part I need, because I can't google for the name of it correctly.  I've tried servo input shaft, and many other things that don't make sense.

More Info.
I have a servo on a machine, and I can not interface with this servo in any way but physically.  I can't read the output from it electronically, and the signals are proprietary.  I can't take anything apart, all I can do is put something physically on it.
So, the issue is, I need to (based on nothing but the position of the servo shaft) figure out what position that 3rd party servo is at.
With that information, I'm then going to man in the middle, and attach another servo to my device, and change the value to what I want.
So if the factory servo is at 50%, and I know that by using something like a rotary encoder, if that ends up being the answer, I then could add x% to my actual servo.

google rotary encoder

please provide a clear description of what you are trying to achieve ... why would you need position feedback from a servo? ... the servo actuator can already be commanded to move to specific angles

@jsotola I'll edit the question now to explain.

@jsotola You should write the rotary encoder as the answer, because this is exactly what I needed to know.  Thank you so much!

What you need is an absolute rotary encoder.
It will provide feedback about the absolute rotational position of the servo shaft.
An encoder that uses gray code is preferred because only one binary bit changes between adjacent positions.


text:
Unpredictable behavior on parsing key-value delimited input from serial
I am having trouble with a "simple" command parser; I'm guessing I'm doing something wrong with memory allocation - appreciate any pointers :)
For context: I'm running on an Arduino Uno (if it matters). The commands I expect are of the form <key1=value1;key2=value2;key3=value3>. For simplicity here (as well as for my own failed attempts at debugging), I've removed everything extraneous, so that this code just prints back to the serial monitor whatever the current value associated with the key "text" is every time a command enclosed in < > is encountered.
This seems to work correctly until after the first time the key is found; then it behaves somewhat unpredictably - haven't yet been able to discern the pattern.  But, for instance, if I send:
<a=5>
-> EMPTY
<b=7;text=here;d=9>
-> here
<d=abc>
-> here
<d=ghi;e=afds>
-> afds

That last displayed value is wrong, since no new key of text was sent over serial. The complete code is here:

// command indicators
char START_MARKER = '<';
char END_MARKER = '>';

const int MAX_KEY_VALUE_PAIRS = 3;  // maximum number of key-value pairs in message
const int MAX_ELEMENT_CHARS = 25;  // the maximum number of characters (+1 for terminator) in a key or a value

// message format: <key1=value1;key2=value2;key3=value3>
const int MAX_MESSAGE_CHARS = (MAX_KEY_VALUE_PAIRS * (MAX_ELEMENT_CHARS + 1)) * 2 + (MAX_KEY_VALUE_PAIRS - 1) + 2;  // maximum message size

char received_chars[MAX_MESSAGE_CHARS];  // <- EDIT#1
char received_chars[30] ={'\0'};
bool new_data = false;

char *text;  // the value identified by the "text" keyword, i.e.: in <text=abc;time=814a>, text would be abc.

void ParseData(char *str) {
  // This picks off the ;-delimited key-value pairs and assigns them to a multi-dim array
  char * pch;
  int pairs_count = 0;
  char config[MAX_KEY_VALUE_PAIRS][2][MAX_ELEMENT_CHARS];

  pch = strtok(str, "=");

  while (pch != NULL)
  {
    strcpy(config[pairs_count][0], pch);
    pch = strtok(NULL, ";");
    if (pch == NULL) break;

    strcpy(config[pairs_count][1], pch);
    pairs_count++;
    pch = strtok(NULL, "=");
    if (pch == NULL) break;
  }

  for(int i=0;i<pairs_count;i++) {
    if (strcmp(config[i][0], "text")==0) text = config[i][1];
  }
  Serial.println(text);
}

void ReadSerial(){
  // After calling ReceiveText to empty the buffer, if a complete command has been found,
  // parse that command.
  new_data = ReceiveText();
  if (new_data == true) {
    char temp_chars[MAX_MESSAGE_CHARS];  // temporary array for use when parsing
    strcpy(temp_chars, received_chars);
    received_chars[0] = '\0';  // <- EDIT#2
    ParseData(temp_chars);
  }
}

boolean ReceiveText() {
  // This dumps the characters on the buffer so far received_chars, searching for an END_MARKER
  // along the way; if it finds one, it goes back to find a START_MARKER; if that is also found,
  // the string within is the ;-delimited set of key value pairs
  static boolean recv_in_progress = false;
  static byte ndx = 0;
  char rc;

  boolean new_data = false;
  while (Serial.available() > 0 && new_data == false) {
    rc = Serial.read();

    if (recv_in_progress == true) {
      if (rc != END_MARKER) {
        received_chars[ndx] = rc;
        ndx++;
        if (ndx >= MAX_MESSAGE_CHARS) {
          ndx = MAX_MESSAGE_CHARS - 1;
        }
      } else {
        received_chars[ndx] = '\0'; // terminate the string
        recv_in_progress = false;
        ndx = 0;
        new_data = true;
      }
    } else if (rc == START_MARKER) {
        recv_in_progress = true;
    }
  }
  return new_data;
}

void setup() {
  Serial.begin(9600);
  text = (char*)malloc(25);
  strcpy(text, "EMPTY");
  received_chars[0] = '\0';
}

void loop() {
  ReadSerial();
}

Thanks!

Are your "keys" pre-defined values? Or is this intended to allow absolutely anything to be entered as a "key"?

At present, they're defined so as to allow anything to be entered as a key.

Is that really what you want? Personally I usually define a struct to take the data and do string matching on the key to work out which entry in the struct to assign the value to. You also parse the value according to what the type is, so numbers are stored as integers, etc.

The way you use malloc and changing the pointer of dynamic created variable will cause memory leak. As for the problem, you are picking up the memory content left by the previous buffer.

Welcome to the I forgot to empty my buffer char club (I lost some days finding a simlar problem)
 strcpy(temp_chars, received_chars)  // strcpy empties temp_chars and adds the received_chars

but you have no (for me) visible routine to empty received_chars
Do this either by setting
received_chars[0] ='\0'; // set the pointer to first index

or
 received_chars ="0";

or
strcpy(received_chars,"0");

after you used the buffer content. By using
static byte ndx = 0;

you just set the pointer and then start to write, as a safequard you should first reset the end terminator and then start to write. This is probably the reason you see characters even if no key is pressed due to a still "full" charbuffer.To prevent heap corruption define your received_chars as a fixed arraybefore setup:
char received_chars[128] ={'\0'}; // 127 chars + terminator

if you use malloc you have to use free, but doing that with a lot of dynamic data causes heap fracturing -> crash in the end
EDIT
The program does now the following

ignores all char not enclosed by <>
check for text and displays everything after = and before;
ignores everything after ; if its not text= again
if its text= again ignores the first and only displays the second param

You do not need strtok here as it deletes chars I use a modified substring routne for char arrays.
Here is the code working as described above:
// command indicators
const char START_MARKER = '<';
const char END_MARKER = '>';

const uint8_t MAX_KEY_VALUE_PAIRS = 3;  // maximum number of key-value pairs in message
const uint8_t MAX_ELEMENT_CHARS = 25;  // the maximum number of characters (+1 for terminator) in a key or a value

// message format: <key1=value1;key2=value2;key3=value3>
const uint8_t MAX_MESSAGE_CHARS = (MAX_KEY_VALUE_PAIRS * (MAX_ELEMENT_CHARS + 1)) * 2 + (MAX_KEY_VALUE_PAIRS - 1) + 2;  // maximum message size

//char received_chars[MAX_MESSAGE_CHARS] = {'\0'};// <- EDIT#1
char received_chars[256] = {'\0'};
bool new_data = false;
char text[25] =  {'\0'};      // the value identified by the "text" keyword, i.e.: in <text=abc;time=814a>, text would be abc.

void ParseData(char *str) {
  // This picks off the ;-delimited key-value pairs and assigns them to a multi-dim array
  char * pch;
  int pairs_count = 0;
  char config[MAX_KEY_VALUE_PAIRS][2][MAX_ELEMENT_CHARS];

  pch = strtok(str, "=");

  while (pch != NULL)  {
    strcpy(config[pairs_count][0], pch);
    pch = strtok(NULL, ";");
    if (pch == NULL) break;

    strcpy(config[pairs_count][1], pch);
    pairs_count++;
    pch = strtok(NULL, "=");
    if (pch == NULL) break;
  }

  for (uint8_t i = 0; i < pairs_count; i++) {
    if (strcmp(config[i][0], "text") == 0) strcpy (text,config[i][1]);
  }
  Serial.println(text);
}

void ReadSerial() {
  // After calling ReceiveText to empty the buffer, if a complete command has been found,
  // parse that command.
  new_data = ReceiveText();
  if (new_data == true) {
    char temp_chars[MAX_MESSAGE_CHARS];  // temporary array for use when parsing
    strcpy(temp_chars, received_chars);
    received_chars[0] = '\0';  // <- EDIT#2
    ParseData(temp_chars);
  }
}

bool ReceiveText() {
  // This dumps the characters on the buffer so far received_chars, searching for an END_MARKER
  // along the way; if it finds one, it goes back to find a START_MARKER; if that is also found,
  // the string within is the ;-delimited set of key value pairs
  static boolean recv_in_progress = false;
  static byte ndx = 0;
  char rc;

  bool new_data = false;
  while (Serial.available() > 0 && new_data == false) {
    rc = Serial.read();

    if (recv_in_progress == true) {
      if (rc != END_MARKER) {
        received_chars[ndx] = rc;
        ndx++;
        if (ndx >= MAX_MESSAGE_CHARS) {
          ndx = MAX_MESSAGE_CHARS - 1;
        }
      } else {
        received_chars[ndx] = '\0'; // terminate the string
        recv_in_progress = false;
        ndx = 0;
        new_data = true;
      }
    } else if (rc == START_MARKER) {
      recv_in_progress = true;
    }
  }
  return new_data;
}

void setup() {
  Serial.begin(115200);
   strcpy (text, "EMPTY");
 //  text = (char*)malloc(25);
//  received_chars[0] = '\0';
}

void loop() {
  ReadSerial();
}

If you could describe what you really want in the end I'm sure we can help with some basic routines.

Thanks for the idea - I've made those changes, both to initialize in setup, and immediately after the strcopy, with the received_chars[0] = '\0'; suggestion. Alas, I still get the same bad behavior. But perhaps I misunderstood your suggestion.

Please edit your question with the updated code

Done - yes, that probably helps you see exactly what I did (wrong) :P

Thank you - following your code highlighted my errant ways. Specifically, once I found the keyword "text", I was using text = config[i][1];, whereas I should have been using strcopy(text, config[i][1];. Appreciate the help!

Please mark as solved/accepted - Thanks

The problem was that, in the variables I wanted to keep (i.e.: text in the code below), I was assigning the value of a pointer to the parsed string which is reused the next time a command is found, rather than copying the string.
Fixed code below - see comment Fig#1. There's also a second fix, although that wasn't causing the problem behavior.
// command indicators
char START_MARKER = '<';
char END_MARKER = '>';

const int MAX_KEY_VALUE_PAIRS = 3;  // maximum number of key-value pairs in message
const int MAX_ELEMENT_CHARS = 25;  // the maximum number of characters (+1 for terminator) in a key or a value

// message format: <key1=value1;key2=value2;key3=value3>
const int MAX_MESSAGE_CHARS = (MAX_KEY_VALUE_PAIRS * (MAX_ELEMENT_CHARS + 1)) * 2 + (MAX_KEY_VALUE_PAIRS - 1) + 2;  // maximum message size

char received_chars[MAX_MESSAGE_CHARS];
bool new_data = false;

char *text;  // the value identified by the "text" keyword, i.e.: in <text=abc;time=814a>, text would be abc.

void ParseData(char *str) {
  // This picks off the ;-delimited key-value pairs and assigns them to a multi-dim array
  char * pch;
  int pairs_count = 0;
  char config[MAX_KEY_VALUE_PAIRS][2][MAX_ELEMENT_CHARS];

  pch = strtok(str, "=");

  while (pch != NULL)
  {
    strcpy(config[pairs_count][0], pch);
    pch = strtok(NULL, ";");
    if (pch == NULL) break;

    strcpy(config[pairs_count][1], pch);
    pairs_count++;
    pch = strtok(NULL, "=");
    if (pch == NULL) break;
  }

  for(int i=0;i<pairs_count;i++) {
    if (strcmp(config[i][0], "text")==0) strcpy(text, config[i][1]);  // Fix#1
  }
  Serial.println(text);
}

void ReadSerial(){
  // After calling ReceiveText to empty the buffer, if a complete command has been found,
  // parse that command.
  new_data = ReceiveText();
  if (new_data == true) {
    char temp_chars[MAX_MESSAGE_CHARS];  // temporary array for use when parsing
    strcpy(temp_chars, received_chars);
    received_chars[0] = '\0';  // Fix #2 - wasn't causing this problem, but still was wrong
    ParseData(temp_chars);
  }
}

boolean ReceiveText() {
  // This dumps the characters on the buffer so far received_chars, searching for an END_MARKER
  // along the way; if it finds one, it goes back to find a START_MARKER; if that is also found,
  // the string within is the ;-delimited set of key value pairs
  static boolean recv_in_progress = false;
  static byte ndx = 0;
  char rc;

  boolean new_data = false;
  while (Serial.available() > 0 && new_data == false) {
    rc = Serial.read();

    if (recv_in_progress == true) {
      if (rc != END_MARKER) {
        received_chars[ndx] = rc;
        ndx++;
        if (ndx >= MAX_MESSAGE_CHARS) {
          ndx = MAX_MESSAGE_CHARS - 1;
        }
      } else {
        received_chars[ndx] = '\0'; // terminate the string
        recv_in_progress = false;
        ndx = 0;
        new_data = true;
      }
    } else if (rc == START_MARKER) {
        recv_in_progress = true;
    }
  }
  return new_data;
}

void setup() {
  Serial.begin(9600);
  text = (char*)malloc(25);
  strcpy(text, "EMPTY");
  received_chars[0] = '\0';
}

void loop() {
  ReadSerial();
}

Thanks to Codebreaker007 for the help.


text:
Object composition (class uses class)
I would like to write a class which utilises another class and it´s member functions. I found out that this is object composition and read some examples of how to do it but it ither doesn´t work for me or I just don´t understand it completely. Here are parts of my code.
#include <SPFD5408_Adafruit_GFX.h>    // Core graphics library
#include <SPFD5408_Adafruit_TFTLCD.h> // Hardware-specific library
#include <SPFD5408_TouchScreen.h>     // Touch library
#include <TriangleButton.h>        // TriangleButton library

I want to use an Adafruit_TFTLCD object and its member functions inside my own class TriangleButton. The object tft is initialised before setup.
Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET); //Class is part of SPFD5408_Adafruit_TFTLCD.h

I built the TriangleButton.h similar to this thread (Use object of other class within class) and used a reference to the tft object.
/*
  TriangleButton.h - Library for for constructing and reading triangle Buttons.
*/
#ifndef TriangleButton_h
#define TriangleButton_h

#include "Arduino.h"
#include <SPFD5408_Adafruit_TFTLCD.h>

class TriangleButton
{
  public:

    TriangleButton(Adafruit_TFTLCD &tft, int16_t coordX, int16_t coordY, int16_t orientation, uint16_t size, uint16_t color) : _tft(tft){}
    boolean IsTriggered();
    void dash();
  private:

    Adafruit_TFTLCD &_tft;
    int16_t _coordX;
    int16_t _coordY;
    int16_t _orientation;
    int16_t _size;
    int16_t _color;
    int16_t _ru;
    int16_t _hc;
};

#endif

In the ccp. i put a coresponding constructor.
TriangleButton::TriangleButton(Adafruit_TFTLCD &tft, int16_t coordX, int16_t coordY, int16_t orientation, uint16_t size, uint16_t color)
:
_tft(tft)

Now i get the following error message:
C:\Users\Erik\Documents\Arduino\libraries\AquariumController_Library\TriangleButton.cpp:19:1: error: redefinition of 'TriangleButton::TriangleButton(Adafruit_TFTLCD&, int16_t, int16_t, int16_t, uint16_t, uint16_t)'
TriangleButton::TriangleButton(Adafruit_TFTLCD &tft, int16_t coordX, int16_t coordY, int16_t orientation, uint16_t size, uint16_t color)
^~~~~~~~~~~~~~
In file included from C:\Users\Erik\Documents\Arduino\libraries\AquariumController_Library\TriangleButton.cpp:7:0:
C:\Users\Erik\Documents\Arduino\libraries\AquariumController_Library\TriangleButton.h:14:5: note: 'TriangleButton::TriangleButton(Adafruit_TFTLCD&, int16_t, int16_t, int16_t, uint16_t, uint16_t)' previously defined here
TriangleButton(Adafruit_TFTLCD &tft, int16_t coordX, int16_t coordY, int16_t orientation, uint16_t size, uint16_t color) : _tft(tft){}
^~~~~~~~~~~~~~
exit status 1
I don`t understand why ther is a redefinition. Can somebody explain it to me?

error: class 'TriangleButton' does not have any field named '_tft'

This should be self-explanatory. When you write in the constructor

_tft(tft)

It means “initialize the property _tft of this object with the
parameter tft.
It is not very clear what you mean by “object composition”. In the usual
sense, it means that object A either is or has an object B. In your
case, it seems like you want your TriangleButton to hold a reference
to an Adafruit_TFTLCD. This is not really composition, as your class
neither is nor has an LCD.
As an immediate solution, just add an appropriate data member to the
class:
Adafruit_TFTLCD &_ftf;

Assuming that holding a reference to the LCD is really what you want for
your class, this should be enough to solve your issue.

Edit: To answer the edited question.
“Redefinition” means you are defining again something that has already
been defined before. In this case, the constructor is defined inline in
the header file:
TriangleButton(Adafruit_TFTLCD &tft,
        int16_t coordX, int16_t coordY,
        int16_t orientation, uint16_t size, uint16_t color)
    : _tft(tft){}

(yes, that's a complete definition with an empty body).
And then you try to define it again in the cpp file. This is an error,
every method should be defined only once. At your choosing, it can be
either inline in the header or in the .cpp, but not both.

Thank you Edgar for your explaination. You are right this is not a composition but a reference. Your advice of adding the data member solved the error with the missing field. I updated my code in the question. Now i have a problem with a redefinition. Can you help me?

@ErikWeisbrod: See amended answer.

Thank you Edgar once again now the code compiles. I did not know about the possibility to use an inline constructor in the header file. If i define the constructor in the ccp. do i still need the TriangleButton in the header?

@ErikWeisbrod: If you define the constructor in the .cpp file, you still have to declare it in the class definition within the header file: TriangleButton(parameter list...);. Note that the declaration has no initialization list (i.e. : _tft(tft)) nor a function body ({}), and it ends with a semicolon (;).


text:
Can Arduino UNO permanently store a code?
I'm really new to Arduino and wanted to know if I can make Arduino a permanent controller?
and could you help me with a cheaper alternative?
I also wanted to know about "fuse", i read it somewhere that i can protect the code from someone else who wishes to use, using a FUSE.
Thanks a lot for helping me out:)

hi thanks chris, appreciate your help, so basically i'm coding for an arduino to use it in a product commercially but since i'm really new to this idk if the arduino stores the code for ever. secondly i wish to protect the code from being copied, to a great extent.

The search keywords you are looking for are “AVR lock bits”.

idk if the arduino stores the code for ever

The code is saved in the flash memory, which is non-volatile. It does not lose its content during power cycles. Also, when looking at the time dimension, it holds the code over a very long time, though not for ever. The datasheet of the Atmega328p (the microcontroller in the Arduino Uno or Nano) states:

Reliability Qualification results show that the projected data retention failure rate is much less than 1 PPM over 20 years at 85°C or 100 years at 25°C.

So over 20 years at a temperature of 85°C you can get 0.0001% of data loss in the flash memory. At normal room temperature you can get that loss in 100 years. So significantly longer than the lifetime of most electronic products.

I also wanted to know about "fuse", i read it somewhere that i can protect the code from someone else who wishes to use, using a FUSE.

There are different ways and levels of protection. Though that is a more advanced topic, that you should tackle, when your product is finished otherwise. There are multiple resources on the web about this. The first place to look is always the datasheet of the used microcontroller. First part might be to not use the standard Arduino bootloader, but your own. And then you can set 2 fuses for getting different levels of protection (write protection, read protection), that will lock out 99% of the people. This question on Electrical SE might also be interresting for you. You can find many resources on the web by searching for something like "Arduino code protection" or "AVR code protection" (if you are using an AVR based microcontroller like with the Arduino Uno/Nano/Mega)

Apart from that I also would open the question to you, if your code is really that new and ingenious, that you need to protect it from being read that way? It might totally be, that this is the case for you. But from my perspective the probability is very low. I cannot say of my own codes, that they are worth the hassle of protection. And it also depends on what you really want to prevent that way.
For context: When you program the Arduino (or any microcontroller) with your C/C++ program, the text of the program is not saved on the Arduino. Instead the code is first converted to Assembler code and then compiled into binary machine code. On that level all the nice concepts of the higher level languages are not present, so they are done by multiple lower level functions (for example loops are jumps with conditions). An attacker might read the machine code back from the microcontroller. The biggest threat here is, that he would just copy it to a new microcontroller.
If he wants to get "code" from it, he would invoke a disassembler, which converts the machine code back to the assembler language. But at this point all symbols (names of variables, functions, ...) are lost, because they are not saved in the original machine code from the start. Reading and understanding such a code is very difficult, especially, if your code is rather big and complex. Most times it would be easier for an attacker to just reverse engineer your code based on the behavior of the original microcontroller.
So in the end, you cannot really prevent people from building counterfeit products. That's what a patent is for.
This does not mean, that you should not use the code protection. Just do a realistic security assessment and then decide, if it is worth the hassle.

Right.  Protecting your code with lock bits is not any way to prevent someone like me from copying your code.  I don’t need to see your code to copy it.  If you really think your idea is that unique then patent it.  Otherwise lock bits are like locking the doors to prevent a thief who just comes in through the window instead.  Long ago the way to make money on code was to keep it secret and prevent anyone from getting it without paying.  That’s not a very good business model anymore.  It guarantees that you won’t sell for long because those products are the first to get freeware versions.

I'm just knew to this environment, so I guess I was overexcited but the way you guys have explained(chrisl and Delta_G) I really appreciate it. Thank you!!!