text:
What are the traditional ways to optimize program memory usage?
While doing big projects using Arduino boards (Uno, Atmega328P MCU). I used to get warnings like this
Sketch uses 13764 bytes (44%) of program storage space. Maximum is 30720 bytes.
Global variables use 1681 bytes (82%) of dynamic memory, leaving 367 bytes for local variables. Maximum is 2048 bytes.

Low memory available, stability problems may occur.

What are the generally practiced methods for the optimization program memory usage?
Is there any difference in memory usage if the variable is declared globally or locally.
Will it matter what the control statement/selection statements are (like if, switch )
Usage of Serial monitor. Serial.print()
......

Low memory available, stability problems may occur.

How bad are these warnings?
Before marking it duplicate, I have referred the following. But it wasn't satisfactory
Most memory efficient way to program
What are safe memory usage limits?

not a traditional way, but Nano Every has 3 times the SRAM of classic Nano and the updated compiler doesn't copy constant strings into SRAM.

What are the generally practiced methods for the optimization program
memory usage?

First, note you are searching for ways to lower SRAM memory. This contains global (variable) memory and heap space (dynamic memory + stack memory).

Avoid memory gaps, by not using dynamic memory (with free/malloc/new).
Avoid using the String class.
Avoid global memory in SRAM by using PROGMEM, F(..) if possible.
Use the smallest variable size (e.g. uint8_t instead of int).
Store arrays of booleans into bits (8 booleans per byte).
Use bit flags if applicable.
Use some compressed type of memory internally (affects performance), e.g. if you have many 6 bit values to store, store them not in separate bytes but use 6 bytes for 8 times 6 bit values).
Avoid passing arrays by value.
Avoid a deep call stack with many (big) variables. Note this affects your design, so use it as a last resort.
If you need a calculatable table, calculate each value instead of storing it as a table.
Do not use longer arrays than needed, and think about reasonable maximum array sizes otherwise (see hcheung's comment below).
(this is not a complete list).

Is there any difference in memory usage if the variable is declared
globally or locally.

Yes, local variables are added to the stack, but are removed after the function ends, global variables stay (but are only created once).
Note that variables on the stack (and also dynamic memory) are NOT taken into account in the memory calculated in the warning message during compiling.

Will it matter what the control statement/selection statements are
(like if, switch )

No, this will only affect the program memory.

Usage of Serial monitor. Serial.print()

Probably yes, the serial monitor probably reserves (quite?) some memory as a buffer.

Low memory available, stability problems may occur.
How bad are these warnings?

How bad it is, depends on how much memory is used which is not calculated, which is dynamic memory, and stack memory.
You can calculate it manually (which can be quite cumbersome for a big program), you can also use the GitHub library for this:
Arduino MemoryFree
If you know how much heap memory you use worst case, than add it to the calculated global variables memory. If this is less than your maximum available SRAM memory, you are safe.

Upvote for the comprehensive summary. I'd like to add one more "allocate your array size according to the need", I often see many ArduinoJson users created an allocation as large as 1024 bytes with StaticJsonDocument<1024> doc; for a target data object consists of only a couple of key/value pairs that take no more than 50 bytes.

@hcheung ... good one ... for me it's obvious not to use too many, but with limited RAM system you have to think about array limits carefully.

What about macros like #define

@MayooghGirish #define's are only textual substitutions, the result of the substitution can be applied to the examples mentioned in my list.

Nitpick: I would say "avoid using String" rather than "prevent using String". "Avoid" means that you should not do it. "Prevent" means you should make it so someone else cannot do it, or so it cannot happen by itself. Likewise, "avoid storing constant global variables in SRAM" (the constant part is important, you can't just move anything to PROGMEM!)

@user253751 You are right thanks, English is not my native language. I will change it in my answer.

I've made a few more changes, in case you want to check them.

@user253751 All accepted, I used 'sketch'  because in Arduino it's the 'default'  term, although I prefer program as it's used everywhere else.

Arduino programs are called sketches, but I think program memory is still called program memory, not sketch memory. For example PROGMEM

@user253751 That's correct. Probably Arduino used 'sketch' as it seems less 'difficult'  than a program.

I just want to add a single bullet to Michel Keijzers’ excellent answer:

think about every single item you are storing in memory and ask
yourself the question: do I really need to keep this in RAM?

It may sound silly to state what many would consider obvious, but we
have seen here many instances of novices who do not take this into
consideration. As a simple example, consider this function that averages
500 analog readings:
int averageAnalogReading()
{
    // First take and store the readings.
    int readings[500];
    for (int i = 0; i < 500; i++)
        readings[i] = analogRead(inputPin);

    // Then compute the average.
    long sum = 0;
    for (int i = 0; i < 500; i++)
        sum += readings[i];
    return sum / 500;
}

Storing all those readings is completely useless, as you can just update
the sum on the fly:
int averageAnalogReading()
{
    long sum = 0;
    for (int i = 0; i < 500; i++)
        sum += analogRead(inputPin);
    return sum / 500;
}

For the same reason, if you need some kind of running average to smooth
data, you should consider using an exponentially-weighted running
average, which can be incrementally updated without storing the
readings.

Upvoted, very good point. The best way to improve is to check the algorithms itself.
Short note: if you are interested in averages, also look at 'moving averages', also not costing additional SRAM for each measurement made.

@MichelKeijzers If you want a proper box-filter moving average then you do need to store the last N measurements. But if you can change it to an exponential filter, then you don't.

@user253751 You are right in that. Thanks for the clarification.

What are the generally practiced methods for the optimization program memory usage?

(nb. as per Edgar's comment I emphasise that this is about using PROGMEM more efficiently.)

If you can replace code with a table whose size is ≤ the lines of code, do it.

Instead of using a sequence of ifs, find a way to collapse the procedure into a table
Use tables of function pointers if it makes sense
Sometimes you can come up with a mini-language that is much more dense than AVR instructions, for example encoding robot logic into 16 commands, and then you can pack two commands per byte. This could collapse your memory usage 50-fold.

Use functions instead of repeated code—this may sound obvious but there are often subtle ways of rewriting code (but bear in mind that function calls have overhead)
Use hash tables rather than tables with big gaps
Use fixed point rather than floating point (e.g. you can take a byte and interpret its value as ranging from 0.00 to 2.55, instead of using a 4-byte float)

Is there any difference in memory usage if the variable is declared globally or locally.

Let's talk about the stack.
void A() {
    byte a[600];
    ...
}
void B() {
    byte b[400];
    ...
}
void loop() {
    byte xxx[1000];
    ...
}

This program will firstly use at least 1000 bytes of RAM all the time. There is no real difference compared to declaring xxx globally. But then what is critical is which function calls which.
If loop() calls A(), and then loop() calls B(), the program will not use more than 1600 at any time. However, if A() calls B(), or vice versa, the program will use 2000. To illustrate:
loop() [1000]
  └──── A() [1600]
  │    [1000]
  └──── B() [1400]
  └──── A() [1600]
  └──── B() [1400]

versus
loop() [1000]
  └──── A() [1600]
        └──── B() [2000]
  │    [1000]
  └──── A() [1600]
        └──── B() [2000]

Will it matter what the control statement/selection statements are (like if, switch )

Not much difference for a small number of cases. Otherwise it depends on your code. The best way is to just try both and see which is better. But:
switches usually use jump tables which are quite compact if you cover nearly every case in a range (0,1,2,3,4,..,100). ifs usually use a sequence of instructions, which take up more bytes and cycles than a jump table entry, but it makes more sense if you don't have a consecutive stretch of cases.

Usage of Serial monitor. Serial.print()

I don't believe that makes a lick of difference. Serial buffers are tiny (say 64 bytes, or 128 for a bigger board) and I believe they are allocated whether or not you use Serial.
Of course "literal strings like this" and char[] buffers consume memory. You can comment them out (or use #ifdefs) when you don't need them.

Note that your first 5 bullet points are about saving flash rather than saving RAM. The OP was not short on flash. The tables will actually cost RAM, unless you put them in PROGMEM. 2. Re “There is no real difference compared to declaring xxx globally”: that is, unless setup() is memory-hungry. 3. The serial buffers are not allocated if you don't use Serial.

Thanks @EdgarBonet 1. Yes, I was thinking of PROGMEM, sorry. 2. Could you explain this? Isn't setup()'s stack-allocated memory freed after it runs? 3. Thanks I have edited that.

Re explain point 2: setup() and loop() do not usually run at the same time, so their stack usages do not add up. If you make xxx global, it will be allocated even while setup() is running. This should be no concern unless setup() is itself memory-hungry.

Since you asked for traditional ways, I am going to raise a traditional method.  In this case, more than 50 years old.
Generate and analyze a listing.
Methodology:

Compile all the code with debugging turned on (add -g).

Link the code with debugging turned on, producing an ELF executable.  Do NOT convert to an image loadable on the arduino.

use objdump to make a listing.  My usage of this read:
( avr-objdump --headers --source --disassemble --syms program.elf ; \
  avr-objdump --full-contents --section=.final_progmem program.elf ) > program.lst

Your usage may vary based on what you prefer to see.

The point of this is that this allows you to see exactly what is using every byte of your memory.
You may want to play around with different optimizations, until you understand what you are seeing.  -O0 produces the most comprehensible disassembly, while -Os makes the smallest.
One tip based on having done this:  The Arduino libraries are designed for generality, not speed and memory efficiency.


text:
Is there a way for an Arduino to flash another one without a computer?
I am going to create a game console. The games will be in an SD card and an Arduino (or an Atmega chip) will read a hex file's contents to RAM and will flash it to another one. Something like this but here, the guy says that this only works for atmega328, and I am planning to use a ATSAM3X8E chip and also I am worried about the power levels (5v - 3v3).
Is there any way for me to use an Atmega chip like Atmega16u2 and use that to flash something like an ATSAM3X8E? If so, what protocol should I use and how may I implement it in my code?

That video isn't really relevant. Unless you want to waste two arduinos for this project, which is a bit wasteful. What you want to do is have the Arduino program itself. This is normally done via a bootloader (at least on the ATMegas). I found a bootloader that updates it main program via a SD card

As for the ATSAM, have a look at https://stackoverflow.com/questions/14960075/can-i-run-a-program-from-a-sd-memory-instead-of-flash-on-an-evaluation-board-em

@Gerben I want to waste two arduino's, actually I will use an Atmega16u2 for flashing the ATSAM3X8E from the sd card.

application on ATSAM3X8E  can write to flash without problems so it can update itself. Arduino has SDU library for SAMD21 to load sketch from SD card

@Juraj I need to display a GUI to ask the user about which program to flash.

On which Arduino do you want to run this GUI? The one doing the uploading, or the one running the game (which probably is the one with the screen and buttons)?

@Gerben on the one with a screen and some buttons. Like this: When the console powers up, the Atmega16u2 flashes gui.hex file to the ATSAM3X8E. Then, when user selects a game to load, ATSAM3X8E sends the name of the game to 16u2 and the 16u2 flashes the game to ATSAM3X8E.

I'd have the GUI write the new "programs" id to some file on the SD card and then reset the Arduino. The bootloader can then check this file, to see if it needs to program a new game to flash.

you don't need the 16u2

Good idea @Gerben , I may try that approach.

@Juraj how may I flash then?

read from SD and write to flash. of course there are many details to solve. the SDU library code checks at boot for new firmware binary on SD card and loads it to flash at address after the loader code, then executes it. this is close to what you want.

source: Stack Exchange

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

sort: votes


text:
3.3V to 5V PWM level shift
I need to shift a PWM signal from a ESP32 (3.3V) to receiver that supports 5V. The signal is at maximum of 400Hz. Can this shifter do the job ?

Yes, it can. Though depending on the receiver you may not need it. If the receiver is a 5V Arduino, it will see 3.3V on its digital input pin as HIGH.

Already bought it and it works, and no, the receiver is not an Arduino, it's an ESC (Electronic speed controller) for a quadcopter.

That should work, but it's overkill. Those devices are made for bidirectional signaling. You should be able to use a single transistor that is driven to saturation at 3.3V. A Suitable "logic level" MOSFET with a 3.3 gate voltage should do the trick.
And, as Chris L said in his answer, you may be able to drive an input on a 5V Arduino directly with 3.3V. That's a high enough voltage to be read as a logic level 1.

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


text:
Digispark green led being the only one to turn on
I was doing some tests with an ATtiny85 Digispark module using Arduino IDE on my Windows PC. I was testing some stuff with the DigiKeyboard library from Digistump.
Everything was going fine until suddenly the Digispark stopped working and wasn't able to upload code through the module anymore. Now when I plug it in my PC, the only thing that the module does is turn on the green led; besides, Windows doesn’t recognize the module when I plug it in anymore and doesn’t even appear in Device Manager as an unknown device or something.
I reinstalled the drivers but nothing changed. I also tried to reinstall Micronucleous into the ATtiny85 using Zadig, but wasn’t able to do it because Windows doesn’t recognize the module when I plug it in, so Zadig won't see it either.
Since I’m not very familiar with electronics, I’m not sure if there is any way to fix this or if it’s due to some physical damage, so any help or direction with how to deal with this would be really appreciated.

are you certain that windows is not recognizing anything at all?

Yes. I double checked Device Manager and I couldn't see it there; besides, Windows doesn't play this sound that you hear when a USB device gets connected.

afaik digispark doesn't have USB chip and the Atiny doesn't have native USB. you must program it over ISP. and again afaik, software USB bootloader can be used. a new Digispark should have it.

@Juraj the digispark uses VUSB to implement USB in software. Programming over ISP isn't possible, as far as I know, since Digispark disables the reset pin (to use it as a GPIO).

@Juraj I'm not sure of what you mean, from what I know, the Digispark was made to be able to program the attiny85 via USB. I was able to program this exact Digispark in the past, but in some moment something went wrong and wasn't able to do it anymore

so lost USB indicates lost bootloader. it is time to find out how to burn the bootloader.

@Juraj looks like that is the way to go, thanks!

@vile Do you have any updates? I literally just ran into this issue today....I got various scripts loaded, worked fine, now today suddenly it stopped getting recognized  I tried everything so far, but it's not even showing up on the device manager.


text:
ESP32: How to run two independent PID controllers, one per core?
I want to control 2 independent processes with 2 PID controllers. Is it possible to run each controller on a separate core? I'm using this PID library. According to its documentation, the PID::Compute() function should be called once every loop(). How can this be achieved when using RTOS tasks (for multi core execution)?

why not put both  PID::Compute()  and  PID2::Compute() in loop()? it still will be called once per instance

No that would work but the PID computation algorithm will only run on a single core and that's not what I want to achieve.

still one core runs WiFi

Sure. The existing Arduino setup and loop are just executed in their own task:
void loopTask(void *pvParameters)
{
    setup();
    for(;;) {
        if(loopTaskWDTEnabled){
            esp_task_wdt_reset();
        }
        loop();
    }
}

extern "C" void app_main()
{
    loopTaskWDTEnabled = false;
    initArduino();
    xTaskCreateUniversal(loopTask, "loopTask", 8192, NULL, 1, &loopTaskHandle, CONFIG_ARDUINO_RUNNING_CORE);
}

So there's no reason not to replicate that to give yourself an entire new setup and loop, or just a single function that does it all if you prefer.
TaskHandle_t secondPidTaskHandle;

void secondPidLoop() {
    // setup code here
    for (;;) {
        // PID loop code here
    }
}

void setup() {
    xTaskCreateUniversal(secondPidLoop, "secondPidLoop", 8192, NULL, 1, &secondPidTaskHandle, 0);
}

void loop() {
    // First PID code
}

The last parameter to xTaskCreateUniversal() is the core to execute on. The default setup/loop runs on core 1:
#define CONFIG_ARDUINO_RUNNING_CORE 1

So just use 0 and it'll run it on core 0.

esp32_technical_reference_manual_en.pdf
Page 620
As mentioned before, only an elevated process with PID of 0/1 can initiate a process switch. The new process
may have any PID from 0 ~ 7 after the process switch. The key for successful proactive process switching is that
Espressif Systems 620
Submit Documentation Feedback
ESP32 Technical Reference Manual V4.3
29. PID Controller
when the last command of the current process switches to the first command of the new process, PID should
switch from 0/1 to that of the new process.
The software procedure for proactive process switching is as follows:

Mask all the interrupts except NMI by using software.
Set register PIDCTRL_NMI_MASK_ENABLE_REG to 1 to generate a CPU NMI Interrupt Mask signal.
Configure registers PIDCTRL_PID_DELAY_REG and PIDCTRL_NMI_DELAY_REG.
Configure register PIDCTRL_PID_NEW_REG.
Configure register PIDCTRL_LEVEL_REG and PIDCTRL_FROM_n_REG.
Set register PIDCTRL_PID_CONFIRM_REG and register PIDCTRL_NMI_MASK_DISABLE_REG to 1.
Revoke the masking of all interrupts but NMI.
Switch to the new process and fetch instruction.
Though we can deal with interrupt nesting, an elevated process should not be interrupted during the process
switching, and therefore the interrupts have been masked in step 1 and step 2.
In step 3, the configured values of registers PIDCTRL_PID_DELAY_REG and PIDCTRL_NMI_DELAY_REG will
affect step 6.
In step 4, the configured value of register PIDCTRL_PID_NEW_REG will be the new PID after step 6.
If the system is currently in a nested interrupt and needs to revert to the previous interrupt, register
PIDCTRL_LEVEL_REG must be restored based on the information recorded in register PIDCTRL_FROM_n_REG
in step 5.
In step 6, after the values of register PIDCTRL_PID_CONFIRM_REG and register
PIDCTRL_NMI_MASK_DISABLE_REG are set to 1, PID Controller will not immediately switch PID to the value of
register PIDCTRL_PID_NEW_REG, nor disable CPU NMI Interrupt Mask signal at once. Instead, PID Controller
performs each task after a different number of clock cycles. The numbers of clock cycles are the values specified
in register PIDCTRL_PID_DELAY_REG and PIDCTRL_NMI_DELAY_REG respectively.
In step 7, other tasks can be implemented as well. To do this, the cost of those tasks should be included when
configuring registers PIDCTRL_PID_DELAY_REG and PIDCTRL_NMI_DELAY_REG in step 3.
Espressif Systems 621
Submit Documentation


text:
What else is consuming Data Segment reported by avr-size?
I am facing a low memory available problem in arduino. I am compiling a big sketch for arduino mega 2560.
Analysing a .elf file, the avr-size tool gives:
text    data     bss     dec     hex filename
68524   4392    2560   75476   126d4 C:\Users\LEAN...

And the avr-nm (avr-nm doc) shows only variables with t, T, b, d and B. The following is how the command is executed (the output is being saved in a file called test.txt).
   avr-nm -a -td -C -l --size-sort -r x.elf >> test.txt

Then, I perform a sum to confirm the avr-size result using this Python script:
f = open("test.txt", "r")
lines = f.readlines()
f.close()

su = 0
dsum = 0
bsum = 0
tsum = 0
gsum = 0
for line in lines:
    #print(line, end="")
    s = line.split()
    try:
        val = int(s[0])
        su = su + val
        if(s[1].lower() == 'b'):
            bsum = bsum + val
        if(s[1].lower() == 'd'):
            print(line)
            dsum = dsum + val
        if(s[1].lower() == 't'):
            tsum = tsum + val
        if(s[1].lower() == 'g'):
            gsum = gsum + val
    except:
        print("ERR: ",s[0])
print("\n\nSIZE: ", su)
print("SIZE d/D: ", dsum)
print("SIZE b/B: ", bsum)
print("SIZE t/T: ", tsum)
print("SIZE g/G: ", gsum)

and the sum result of each var type is:
SIZE:  71015
SIZE d/D:  135
SIZE b/B:  2560
SIZE t/T:  68320
SIZE g/G:  0

The question: Here d/D sums is 135 bytes. So, why the data segment reported by avr-size is 4392 bytes? how to find out what is occupying this space?
Best Regards.
EDIT
It must be a Joke!
I have a lot of like this in the code:
Serial.print("QTDE REG: ");

Just changing for this:
Serial.print(F("QTDE REG: "));

I have reduced by 10 the .data size!
So, in this way Serial.print("QTDE REG: "); "QTDE REG: " is stored as a global variable?? I thought the compiler would save locally.
EDIT 2
I have an advance running avr-objdump -s -j .data x.elf as suggested by Edgar below. Now I see that all my string literals are in data! For example:
void myFunction(){
    ...
    sprintf(buf, "{\"name\":\"Intervalo de Registros\",\"value\":\"%d\", \"unit\":\"C\"},", (int)settings.treg);
    ...
}

avr-objdump -s -j .data x.elf shows:
 800660 2c007b22 6e616d65 223a2249 6e746572  ,.{"name":"Inter
 800670 76616c6f 20646520 52656769 7374726f  valo de Registro
 800680 73222c22 76616c75 65223a22 2564222c  s","value":"%d",
 800690 2022756e 6974223a 2243227d 2c007b22   "unit":"C"},.{"

EDIT 3
As commented, all string literals are saved in the (SRAM). So, the problem is, I have a lot of strings literals spread across different functions. How to save this amount of SRAM? Note that using F() for sprintf gives compilation error.
Is there any way to put the literal in stack (release memory when function returns) and not in the global area? Is F() the only solution?
============ SOLUTION ============
For now, I have found this solution: use sprintf_P with PSTR(...) in the same way of F(...):
sprintf_P(buf, PSTR("{\"name\":\"Intervalo de Registros\",\"value\":\"%d\", \"unit\":\"C\"},"), (int)settings.treg);

I will test more...
Thanks for all clarification!
Best Regards!

all the string literals are copied to SRAM with older versions of avr gcc. F macro ensures they are read from flash.

@Juraj but when the function returns the space allocated is released? seems that all my literals goes to data segment, which is a place for global vars.

sorry, it should be "all the string literals are copied to SRAM at boot"

https://www.arduino.cc/reference/en/language/variables/utilities/progmem/#_the_f_macro

Most of the missing data section is probably made of string literals.
When you write something like
Serial.println("Hello, World!");

the string "Hello, World!" is implemented by the compiler as an
anonymous array of characters, and the address of this array is
provided to the println() method. Since the array is anonymous, it
doesn't show up in the output of avr-nm. You can check that this is
the case by looking at the actual contents of the section:
avr-objdump -s -j .data x.elf

And you can avoid this by wrapping the strings in the F() macro:
Serial.println(F("Hello, World!"));

This has the effect of keeping the string in flash, and passing the
flash address to the println() method. Note that this is actually a
different, overloaded method, that knows how to retrieve the character
data from flash.

Edit: Adding some clarifications.
All this complexity about flash vs. RAM storage comes from the fact that
the AVR uses a Harvard architecture, where RAM and flash are
in different address spaces, accessed through different memory buses
using different machine instructions. Unlike C, the C++
language has no notion of address spaces, and the compiler simply
assumes that any pointer to function holds a flash address, whereas any
pointer to data holds a RAM address.
Per the rules of the language, a string literal has the type
const char *, and a function that should be able to accept a string
literal should take a const char * parameter. Since these are pointers
to data, when you dereference them the compiler emits the machine
instructions that are appropriate for reading RAM. This is why the
compiler puts all string literals in the .data section of the flash: at
program startup, the C runtime copies them to the .data section of the
RAM, making them accessible to those machine instructions.
The current solution to avoid this useless copy involves a bunch of
preprocessor macros like F(), PSTR(), PROGMEM,
pgm_read_byte()... that expand to compiler extensions or inline
assembly. These allow you to pass around the flash addresses of string
literals disguised as regular data pointers. These pointers should never
be dereferenced with the regular operators of the language (* and
[]), but only through the pgm_read_*() macros. And they should only
be given to functions that do expect these kind of pointers, like
sprintf_P() or Print::println(const __FlashStringHelper *), which is
the println() that gets invoked when using the F() macro.

Is there any way to put the literal in stack

Yes, there is, but it has to be done explicitly:
PROGMEM const char greeting[] = "Hello, World!";

void say_hello() {
    char stack_copy[strlen_P(greeting)+1];
    strcpy_P(stack_copy, greeting);
    Serial.println(stack_copy);
}

As you have already noticed, it is preferable to not put the strings in
RAM at all, and instead use functions like sprintf_P that expect
flash-based strings. However, if you need to use a library function that
expects a RAM-based string, you can use this trick to avoid permanently
committing it to RAM.

Using F() on println saves me about 100bytes. Executing avr-objdump as sugested I see the string of sprintf(buf, "{\"name\":\"Intervalo de Registros\",\"value\":\"%d\", \"unit\":\"C\"},", (int)settings.treg); in it. All strrings are stored in this area?

@LeandroIP: all the string literals, unless using the F() macro or, equivalently, PSTR().

Thanks @Edgar, PSTR() solves the problem with sprintf_P. See SOLUTION in answer for details.


text:
Why is my passive buzzer clicking instead of buzzing when set to HIGH?
everyone. I am working on learning Arduino from scratch and I am on the buzzer lesson. The tutorial I am following consists on writing a code to get an input from the user in the form of an integer number, and, if it is greater than 10 (or whatever threshold you set it to) it will buzz.
I wrote the code exactly as the tutorial said but the buzzer would not buzz, it would do a weird clicking sound instead. I searched for a reason everywhere and could not find an explanation. Most questions in forums were solved by changing the positive wire from the 5V to a regular pin on the board, and those problems were due to the fact that the people asking the questions were not aware that the buzzer was a passive one.
Anyway, I managed to get a buzz by switching from digital to analogWrite and typing a value less than 255. It seemed weird that 255 and HIGH would produce the click, but values less than 255 would buzz, so I tried several analogWrite values:

At 255 the buzzer does the weird clicking.
At 254 the buzzer does a very faint buzz.

The buzzing got louder as I wrote lower numbers until it got stable at around 250, and then got less loud as I decreased the number.
Does anyone know why that is? Is the voltage too much for the buzzer at 255/HIGH? I tried a resistor but still got nothing but clicking with the program set to 255/HIGH.
This is mostly out of curiosity, but I'd still appreciate it if you could answer it.
Here is the code ("Numero" means "number" and "Dame un número" means "Give me a number":
int Numero;

int buzz=10;

int DLY=2000;

String msg="Dame un numero.";

void setup() {

Serial.begin(9600);
pinMode(buzz,OUTPUT);

}

void loop() {

Serial.println(msg);
while (Serial.available()==0){

}

Numero=Serial.parseInt();

if (Numero>25){

  Serial.println(Numero);

  analogWrite(buzz,10);

  delay(DLY);

  digitalWrite(buzz,LOW);

}

}

for passive buzzer use the tone() function. active buzzer makes sound with 5 V only. https://www.arduino.cc/reference/en/language/functions/advanced-io/tone/

those problems were due to the fact that the people asking the questions were not aware that the buzzer was a passive one.

You seem to know, that you have a passive buzzer, but you don't know, what that means for you.
A buzzer consists mostly of a piezo element, which vibrates and thus makes a sound, if you provide it with an alternating voltage. Here we have 2 types of buzzers:

The ones, that generate the alternating voltage themselves, thus only demanding a simple constant voltage from you to operate (these are the active buzzers)
and the ones, that only have the piezo and thus demand to be provided with an alternating voltage by you (these are the passive buzzers).

You have the second type, a passive buzzer. The following is happening:
digitalWrite(pin, HIGH) will only set the pin to HIGH. On the transition from LOW to HIGH, you get a click, because the piezo in the buzzer is reacting to that change. analogWrite() on the other hand generates a PWM signal, which is an alternating voltage (alternating between LOW and HIGH).
When changing the number for analogWrite(), you are not changing the frequency, but only the duty cycle (the ratio of HIGH and LOW times in one period of the signal).

analogWrite(pin, 255) means 100% duty cycle and thus a constant HIGH signal. Actually it is equivalent to digitalWrite(pin, HIGH), because analogWrite() is doing exactly that, if you provide 255 (similarily it uses digitalWrite(pin, LOW), if you provide 0). Thus you again hear the same click.
As the piezo in the buzzer needs to oscillate to make a sound, you need to give him time for getting back to the LOW state. With the analog value 254 the LOW time of the signal is rather small, so that the piezo cannot reach its complete LOW state again. The oscillation amplitude is rather small that way. Thus you only hear a very faint buzz.
With analogWrite(pin, 250) you reached the maximum, because now the piezo has enough time to get to its LOW state again. The amplitude is at its maximum here, thus it is the loudest value.
When going lower than 250 towards zero, you are also reducing the amount of energy, that you give to the buzzer, thus the volume will reduce (though this is certainly not a linear process and depends also on the characteristics of the buzzer).

Just as Juraj already wrote in the comments, a passive buzzer can be interfaced with the tone() function. It will generate the alternating voltage for you and you can even set the frequency to your liking, so that you get tones with different pitches. There are tons of tutorials about the tone() function on the web.

I don't agree with your "When going lower than 250 towards zero, you are also reducing the amount of energy" statement. It reduces the average voltage, but average voltage is not what gets maximum sound out of a piezo emitter. You're going to get the maximum volume out of a piezo element at 50% duty cycle (digitalWrite(pin, 128)).

@DuncanC You mean analogWrite(pin, 128). But as I think closer, you may have a point there. Its difficult to map the duty cycle to the volume. Can you explain more, why at 50% duty cycle you have the highest volume? The piezo is fast enough, so that changes between 5 and 250 would not matter much. When the pin is high, the piezo moves in one direction. When low into the other. In between it stands still. The amplitude is given by the voltage (for the above range), which is equal for all high or low states. Thus I now could say, that in that range the value doesn't matter for the volume.

Or am I thinking wrong here?

Well, to say it will be loudest at 128 is an over-simplification. It will be the closest to a pure tone at 128, and you'll get equal time with the element in the in and out positions. At values other than 128 there will be additional harmonics introduced into the tone. (There's lots of high frequency harmonics in a square wave signal anyway, but at a duty cycle other than 50% there will be even more.)

Hey man, thanks for the explanation. Could not have asked for a better one on passive buzzers. It was clear and concise and solved my burning question. Keep it up.

A passive Piezo buzzer needs excitation to make sound, from your code you have a delay time of 2000 ms.
2000ms means a frequency of 0.5 Hz thats not enough.for my YL-44 Passive buzzer
even the smallest possible number allowed by the arduino delay(ms) function wich is 1 ms isn't enough to hear a clear sound. A frequency of 2000 Khz was good with delayMicroseconds(us).
double outPin = outPin;
double freq_Hz = freq_Hz;
double period_s = 1 / m_freq_Hz;
double period_ms = m_period_s * 1000;
double period_us = m_period_ms * 1000;
void loop() {
 digitalWrite(m_outPin, HIGH);
 delayMicroseconds(period_us / 2);

 digitalWrite(m_outPin, LOW);
 delayMicroseconds(period_us / 2);
}

As chrisl explained, a passive buzzer needs a switched signal of the desired frequency in order to produce a tone of a specific pitch. It's going to produce the best/loudest output with a square wave (50% duty cycle.)
The analogWrite function outputs a PWM (pulse-width modulation) signal. That is a signal of a fixed frequency but varying duty cycle (The ratio of on time to off time.) At 50% (value 128) you should be able to get a decent tone out of it. (It looks like the PWM frequency varies by Arduino model: )
If you want to produce tones of varying frequncies, use the Arudino library's tone() function, documented here: https://www.arduino.cc/reference/en/language/functions/advanced-io/tone/
With the tone() function you provide the pin number and the desired frequency, and it does the rest. As mentioned in the docs, the tone function interferes with PWM output on boards other than Mega.
You could also get a tone with code like this:
bool state = HIGH;
int buzz=10;
unsigned long time = 0;

void setup() {
    pinMode(buzz,OUTPUT);
}

void loop() {
   if (millis() > time) {
      state = state == HIGH ? LOW: HIGH;
      time = millis() + 2;
      digitalWrite(buzz, state);
   }
}

If you loop does nothing else, that should give you a tone of roughly middle C. (250 hz, if my math is correct.)


text:
Serial broken into two shorter shorter strings
I'm trying to do a serial read:
    if (Serial.available() > 0) {
  int inputValue = Serial.read();
  Serial.println();
  Serial.println("I got this:");
  Serial.print(inputValue, BIN);
}

However, it seems that what I receive is always 6 bits first and then followed by 4 bits. I'm really confused. I used a different board just to be sure that it's not just a problem with the board. Could it be the serial monitor I'm using? I'm using the Arduino serial. This is an example of the output:
21:31:02.021 ->
21:31:02.021 -> I got this:
21:31:02.021 -> 110101
21:31:02.021 -> I got this:
21:31:02.021 -> 1010

Can anyone shine a light as to what is happening here?

you are confusing what you receive with what you print

I guess you are sending 5 and have the line ending set to newline only. Then everything is correct and as expected. You see 2 bytes, that are transmitted. Serial.print() will cut out the leading zeros of the byte, so all other digits before that are just zero.
The first byte is the character 5 encoded in ASCII (53 is the decimal representation of the ASCII value here). The second byte is the newline character \n, which marks the end of a line or the end of the data message (depending on the interpretation of the data). If you don't want to send the newline character, select Nothing for the line ending (My Arduino IDE is in German, so I don't know, what exactly is the term in the english version here, but you need to set it for not using any line ending).
As it seems, that you don't know that currently: When you write a number into the serial monitor, you are not sending the direct binary value of that number. You are sending the ASCII representation of the individual digits. ASCII is a system, where the values of a byte represent a character. That includes decimal digits, the alphabet and some special characters. So when you type "255", you are not sending 0b11111111 (1 byte with all bits set --> decimal 255), you are sending 3 bytes with the ASCII byte value for the characters 2, 5 and 5. You can read the byte values for all the characters in tables, just by googling for "ASCII" and looking at the images found.


text:
I can't run shell commands on Linux through AVR sketch (Arduino Yun)
I'm a little confused with some Process.h methods.
I'm trying to run the command "nc 192.168.1.15 9911" to the Linux processor through a sketch.
The appropriate netcat listener is waiting on another computer. Arduino Yun is on the same network with thie computer via WiFi.
When I execute this command through SSH connection on Arduino Yun it works fine, but I can't figure out how it's done through a sketch.
This is my code:
#include <Process.h>

Process p;

void setup() {
   Bridge.begin();
   Serial.begin(9600);
   delay(2000);
   p.begin("nc");
   p.addParameter("192.168.1.15 9911");
   p.run();
   //while (!p.running()) {};

 }

 void loop() {
    if (p.available() > 0) {
    Serial.println("test");
 }
}

This code doesn't seem to work, p.available() nerver executes even if I send data packets.
I also tried p.runShellCommand("nc 192.168.1.15 9911"); with no luck.
It seems that the commands never reach the Linux command line.
Any insights?

and does Serial print something at all? the examples for Yun have SerialUSB for Serial Monitor. https://github.com/arduino-libraries/Bridge/blob/master/examples/Process/Process.ino . and I would add parameters with two addParameter

Nothing at all. I did try this example long ago but it didn't work

There's a few things wrong with your program, some more obvious than others.
First, you have to put each parameter to your shell command in a separate addParameter() call. Otherwise it treats all the parameters as a single parameter and tries to connect you to an address of 192.168.1.15 9911 instead of to port 9911 of address 192.168.1.15.
Secondly you should use runAsynchronously() instead of run() otherwise your sketch blocks at that point until nc terminates. If that never happens then your sketch never gets to the point where it can read the data.
Here is an adaption of your sketch that works for me:
#include <Process.h>

Process p;

void setup() {
    Bridge.begin();
    Console.begin();
    p.begin("nc");
    p.addParameter("192.168.1.15");
    p.addParameter("9911");
    p.runAsynchronously();
}

void loop() {
    static uint32_t ts = millis();

    if (millis() - ts > 1000) {
        Console.println(millis());
        ts = millis();
    }

    if (p.running()) {
        while (p.available()) {
            Console.write(p.read());
        }
    } else {
        Console.println("Restarting process");
        delay(100);
        p.begin("nc");
        p.addParameter("192.168.1.15");
        p.addParameter("9911");
        p.runAsynchronously();
    }
}

It also re-runs nc if / when it terminates. There's also a "heartbeat" printing of millis() so that you can see the sketch is running.  It uses the console, not Serial, for its output, so SSH in to the Yun and telnet localhost 6571 to view the output.

Although right now I don't need to implement the above code because things have changed, your answer solves the current question. Thanks.


text:
Cannot send any UDP packets from ESP8266 Wemos D1
I am attempting to send sensor data from a battery-powered device using UDP. The goal is to send a datagram immediately after the wifi station awakes from sleep then immediately go back to sleep after writing the datagram to a given IP address or hostname.
I can send data to Thingspeak's API using their library so I know the device works, but when attempting to use the WiFiUDP library to send a datagram to an IP address on the same LAN I see nothing happen. My device is getting on the wifi and the udp.endPacket() command is returning successful, but I am not receiving the packets on the server. I know the server works because I can use nc to send UDP packets from other machines on the LAN.
Here is my sketch with the irrelevant bits redacted.
// https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/station-class.html
#include <ESP8266WiFi.h>
// https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/udp-examples.html
#include <WiFiUdp.h>

// Create udp class instance
WiFiUDP udp;

void setup() {
  Serial.begin(115200);
  Serial.print("Connecting to WiFi");
  WiFi.mode(WIFI_STA);
  WiFi.hostname(hostname);
  WiFi.begin(ssid, pass);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.print("SSID:\t");
  Serial.println(WiFi.SSID());

  Serial.print("IP address:\t");
  Serial.println(WiFi.localIP());

  Serial.print("Gateway:\t");
  Serial.println(WiFi.gatewayIP());

  uint8_t buffer[50] = "hello world";
  char message[] = "hello world 2";

  IPAddress staticIP(192, 168, 1, 118);
  udp.beginPacket(staticIP, 3381);
  udp.write(buffer, 11);
  //udp.write(message);
  udp.endPacket();

  // Calculate required sleep time and go to sleep
  long sleepTime = measurementInterval - millis(); // in milliseconds
  if (sleepTime < 100) sleepTime = 100; // set minimum sleep of 0.1 second
  Serial.print ("Going to sleep now for ");
  Serial.print((float)sleepTime / 1000, 3);
  Serial.println (" seconds.");
  Serial.print ("Time going to sleep=");
  Serial.print ((float)millis() / 1000, 3);
  ESP.deepSleep(sleepTime * 5000); // convert to microseconds
}

And my node server just to be complete here:
const dgram = require('dgram')
const server = dgram.createSocket('udp4')

server.on('error', (err) => {
  console.log(`server error:\n${err.stack}`)
  server.close()
})

server.on('message', (msg, rinfo) => {
  console.log(`got message from ${rinfo.address}:${rinfo.port} - ${msg}`)
})

server.on('listening', () => {
  const address = server.address()
  console.log(`server listening ${address.address}:${address.port}`)
})

server.bind(3381)

I've also tried adding delays between each function to no avail.

I don't see udp.begin(). Some Arduino libraries require it even for sending.

run wireshark on your server or on any pc on your LAN ... see what is being sent

@Juraj udp.begin() is for listening, but I did try it and see no difference.

@jsotola wireshark captures no information from the ip of the esp8266 device, udp or otherwise.

you have to send the packets to the IP address of the PC that is running wireshark

@jsotola that is what I tried. I'm thinking it may be a problem with the client software I just don't know what.

Per the esp8266 subreddit, you need to add a sufficient delay() of 50-100 milliseconds (not microseconds) before going to sleep as none of the udp functions are blocking.


text:
Problem with Adafruit_SSD1306 library in .h fie
I have a project which includes OLED display, so I decided to use Adafruit_SSD1306 library. But I have problem with compiling code, which uses this library, in another .h file.
When I use this library in .ino file, everythings works, but in OLED.h file I get this error:
collect2.exe: error: ld returned 1 exit status
Multiple libraries found "DallasTemperature.h"
 Used: C:\Users\luky\Documents\Arduino\libraries\Arduino-Temperature-Control-Library-master
Multiple libraries found "OneWire.h"
 Used: C:\Users\luky\Documents\Arduino\libraries\OneWire-master
Multiple libraries found "SPI.h"
 Used: C:\Users\luky\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.8.0\libraries\SPI
Multiple libraries found "Wire.h"
 Used: C:\Users\luky\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.8.0\libraries\Wire
Multiple libraries found "Adafruit_GFX.h"
 Used: C:\Users\luky\Documents\Arduino\libraries\Adafruit_GFX_Library
Multiple libraries found "Adafruit_SSD1306.h"
 Used: C:\Users\luky\Documents\Arduino\libraries\Adafruit_SSD1306
Multiple libraries found "SrcWrapper.h"
 Used: C:\Users\luky\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.8.0\libraries\SrcWrapper
Byly nalezené násobné knihovny "Adafruit_I2CDevice.h"
 Použitý: C:\Users\luky\Documents\Arduino\libraries\Adafruit_BusIO

The error is from this piece of code:
#include <SPI.h>
#include <Wire.h>

TwoWire Wire1(PB9, PB8); // Use STM32´s I2C2

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

STM32 Bluepill board is used.

Not sure if it solves the problem, but using #include after any code or variable declarations is not good coding practice. Put all #includes at the beginning.

Thanks thats good note.

But its still dont works

Sorry for that ... did you check if you installed multiple same-named libraries (maybe different versions?). Try to compile some sample sketches to see if something is wrong in your own code or within the libraries installation.

Sample sketches compile correctly, also when I use the library in my .ino file, everythings works correctly. Only problem is that my code is very long and it would be very jumble to include all the display code into this main (.ino) file. So I triing to write display code into another .h and .cpp file and then include it into the main file. But that´s the point where I get the compilation error.

Did you use #ifndef ___H checks for not including the same include file twice? (it should not matter for your errors, but something to check).

Yes, I used..
#ifndef __OLED__
#define __OLED__
#endif

You also could check if you can find multiple equally named libraries somewhere on your computer and remove them (after making a backup)

I also tried that. There is just the 1 library. Its very strange problem xD

Than I'm out of ideas ... maybe someone with experience with one of these libraries can answer.

That would be great. Thanks for help Michel Keijzers

Maybe https://www.youtube.com/watch?v=jkNkpzy8TbY helps?

It looks like for some reason it can't find Adafruit_I2CDevice.h which is part of Adafruit_BusIO, which is supposed to be automatically installed when you install Adafruit_SSD1306. Try to install it either via Library Manager on IDE or download it from Adafruit_BusIO. Personally I dislike anything from Adafruit, it is bloated and you ask for a money they gives you the entire jungle with all the dependencies loaded. There are much simpler SSD1602 library out there.


text:
Computer doesn´t recognize MKR1010
I´m learning how to use the Arduino MKR1010. When I wrote a program for controlling LEDs and to read a BMP280 sensor with a web aplication, and I uploaded the program to the board, suddenly the computer did not recognice the board.
The power LED of the board works, but I can't access the board with my computer, and I can't see in the COM ports list, and neither as a "unrecognised device" to reinstall the drivers.
I have tried with a few others USB cables and with another computer, but I still have the same problem. I have also tried to press the reset button reset and I still have the same result. What can I do to make my board work?

The MKR board connects to computer over native USB support of the MCU. The handling of the USB is done by Arduino core functions linked at build to your sketch.
A consequence of using the native USB port is, if your sketch has a problem, it influences the USB communication. In this case you can activate the bootloader to handle the USB port and the upload. It is done by double clicking the reset button on board.
This applies to other SAMD boards (Zero, M0) and to AVR boards with native USB port (Leonardo, Micro) too.

I followed these steps, I connected the board to the computer, the power led is on and the chrd led is on for a few seconds, I press the board button reset two times and the board doesn't do anything. It's possible that the board it's broken?

@mourazo, the onboard LED should start blinking with slow fade.

It  start blinking for a few seconds at the start, later it´s off and i can´t do anything with the board


text:
Simple serial message not consistent (sometimes jumbled up)
I have the following code, it works (most of the time) - yet it's not 100% reliable and now and then will send through a double message on one line or 2 subsequent alpha characters:
const byte interruptPin0 = CONTROLLINO_IN0;
const byte interruptPin1 = CONTROLLINO_IN1;
int counter1 = 0;
int counter2 = 0;
unsigned long previousMillis = 0;
unsigned long interval = 2000;
int a = 60;
char buffer1[256];
char buffer2[256];

void setup()
{
  pinMode(interruptPin0, INPUT_PULLUP);
  pinMode(interruptPin1, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin0), pin1Fired, RISING);
  attachInterrupt(digitalPinToInterrupt(interruptPin1), pin2Fired, RISING);
  Serial.begin(9600);
}

void loop()
{
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    sprintf(buffer1,"A%d",counter1);
    Serial.println(buffer1);
    sprintf(buffer2,"D%d",counter2);
    Serial.println(buffer2);
    counter1 = 0;
    counter2 = 0;
  }
}

void pin1Fired()
{
  counter1 = counter1 + 1;
}

void pin2Fired()
{
  counter2 = counter2 + 1;
}

Result:

This later causes a problem when my code on the other end of the serial comms expects [LETTER][NUMBER].
What have I missed here? I'm relatively new to C for Arduino so quite possibly took a bad approach here?
I've tried to avoid sending serial comms from the interrupt, I read that was risky - hence me tracking the interrupt counts separately.
Can also confirm baud rate matches.
EDIT
To confirm MCU resets I have printed in setup - note: no interrupts firing, still the same issue:

add some printing to setup(). something like Serial.println("START");to see if the MCU doesn't reset for some reason.

Thanks @Juraj - see edit.

which version of Arduino AVR boards package do you use? The newer versions have newer avr-gcc compiler version and it sometimes has strange problems. Try the Arduino AVR boards package 1.6.21. It has the well-tried version of avr-gcc.

Having to use Controllino's own board manager @Juraj

It seems to compile/upload fine with 1.6.21, I'll let this run and see if this has solved it.

This has been running for 2 minutes and hasn't happened even once! If this has worked @Juraj you have saved me a massive headache!

This has happened again unfortunately, very frustrating. You can see from the link here I have to use their board manager: https://www.controllino.biz/knowledge-base/board-library-setup-in-arduino-ide/

Try removing everything related to the interrupt handling (pinMode(), attachInterrupt(), pin*Fired()...) while keeping counter* volatile. Does the problem persist? 2. Could you share the compiled .elf file corresponding to the minimal program that shows the problem? If so, please update the source code in the question to match this minimal program.

Very frustrating time trying to diagnose this.
All credit to Controllino for their support when looking into whether it was a hardware/code issue (it wasn't!).
The problem turned out to be the recipient of these messages. The performance of the PC the Controllino was plugged into was really bad. I noticed what you've seen in the screenshots I've shared every time I'd open a new app or dragged a window.
The serial monitor in the Arduino IDE would lock up for a few seconds and so would miss the serial messages (and have to catch up).

My guess is that an interrupt is occurring during your reading or writing of the counter variables.
Since the variables are bigger than the native size of the registers in the CPU multiple instructions are required to work with them, and an interrupt can occur right in the middle of that work which changes the values it's working on. That can cause a mess (though I wouldn't expect it to make that kind of mess, TBH).
You should wrap all accesses to the counters that aren't in the interrupts inside a critical section. This is a segment of the code where interrupts are not allowed to happen. For obvious reasons you want to keep that code as short as possible.
Also in the code you have given there is no need for your buffers and sprintfs. You can just use multiple Serial.prints to achieve the same result with a much smaller code/memory footprint.
Here's an example:
void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;

    // Copy and reset the counter values in a critical section
    noInterrupts();
    int nowCounter1 = counter1;
    counter1 = 0;
    int nowCounter2 = counter2;
    counter2 = 0;
    interrupts();

    Serial.print("A");
    Serial.println(nowCounter1);
    Serial.print("D");
    Serial.println(nowCounter2);
  }
}

Also your counter variables should be volatile since they are accessed from both the interrupts and the main loop:
volatile int counter1 = 0;
volatile int counter2 = 0;

Thanks for your reply! That makes sense, I do recall seeing 'noInterrupts' and should have known to use it. I've copied the loop example in your answer but it's still happening. Just received A0A0

What board are you using?

Controllino mini

I find it impossible to work out what USB chip they are using in there. It could be a pile of junk for all we know.

This is not an answer, but showing a way to make your code more clean.
Use the critical sections as proposed by Majenko.
You can rewrite
sprintf(buffer1,"A%d",counter1);
Serial.println(buffer1);
sprintf(buffer2,"D%d",counter2);
Serial.println(buffer2);

as
sprintf(buffer, "A%d\r\nD%d", counter1, counter2);
Serial.println(buffer);

Also, an unsigned long int can be maximum around 10 characters (2^32), so including the 'A', 'D', extra new line and \0, a single buffer of around 30 characters will suffice, instead of 2 buffers of 256 bytes (which takes 25% of an Arduino UNO's SRAM).
Also you can rewrite
counter1 = counter1 + 1;

as
counter1++;

which increases a variable with 1.
Also counter1 and counter2 should never be negative so an unsigned type is better.

@EdgarBonet Thanks for that comment, I updated my answer accordingly.

This isn't meant to be a solution; it's more of a workaround.
To avoid repeated letters, you could use code to make sure that each alpha character isn't the same as the one before, and if so, delete the current character before printing.
Then to tackle doubling, if the string has an even number of characters, split the string in half, and if both halves are equal, remove one of them from the string.
This isn't exactly what you wanted but it's more of a worst-case scenario kind of thing.


text:
ATTINY85 - RF Transmitter (RH ASK)
I am working on a small RF sensor powered by a battery.
I used the code from Mr K. (https://arduino.stackexchange.com/a/55516/65870) as base and adapted it to the RH Ask protocol:
#define F_CPU 8000000  // This is used by delay.h library

#include <util/delay.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <util/crc16.h>

#define LED_PIN           0

#define TX_PIN            4 //3
#define TX_BAUDRATE       2000
#define TX_MILLIINTERVAL  (1000UL/TX_BAUDRATE)
#define TX_MICROINTERVAL  (1000000UL/TX_BAUDRATE)
#define TX_MAXLEN         12
#define RFRepetitions 3
byte RollingCounter = 0;

// Define sensor IDs (for MQTT)
#define SensorIDMoisture 6

// Define moisture sensor variables
#define MoistureSensorPinA    A1
#define MoistureSensorPinD    10
#define MoisturePowerOutPin   1
#define RFPowerPin            3 //4

inline void led(const bool onOff) { digitalWrite(LED_PIN, onOff ? HIGH : LOW); }
inline void tx(const bool onOff) { digitalWrite(TX_PIN, onOff ? HIGH : LOW); }

const uint8_t header[8] = { 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x38, 0x2C };
const uint8_t conv4to6[16] = { 0x0D, 0x0E, 0x13, 0x15, 0x16, 0x19, 0x1A, 0x1C,
                               0x23, 0x25, 0x26, 0x29, 0x2A, 0x2C, 0x32, 0x34 };

// Watchdog timer
#ifndef cbi
  #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
  #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

// Important: Sleep time equals the wdt_length setting multiplied by the wdt_loops_max
#define wdt_loops_max 225
#define wdt_length 9 // 9 = 8 seconds

volatile int wdt_loops = wdt_loops_max; // Start with maximum value in order to have a measurement when powering on the system

void rawSend(const uint8_t * p, uint8_t len) {
  while (len--) {
    const uint8_t val = *p++;
    for (uint8_t mask = 1; mask != 0x40; mask <<= 1) {
      tx(val & mask);
      delayMicroseconds(TX_MICROINTERVAL);

//      _delay_ms(TX_MILLIINTERVAL);
    }
  }
}

void send(const uint8_t * buf, const uint8_t len) {
  #define RH_ASK_HEADER_LEN 4
  //  First create the payload ...
  static uint8_t payload[(TX_MAXLEN+3+RH_ASK_HEADER_LEN)*2];
  uint8_t * p = payload;
  uint16_t crc = 0xFFFF;
  uint8_t v = len + 3 + RH_ASK_HEADER_LEN;
  crc = _crc_ccitt_update(crc, v);
  *p++ = conv4to6[v >> 4];
  *p++ = conv4to6[v & 0x0F];

  uint8_t _txHeaderTo = 0xff;
  uint8_t _txHeaderFrom = 0xff;
  uint8_t _txHeaderId = 0;
  uint8_t _txHeaderFlags = 0;

    // Encode the headers
    crc = _crc_ccitt_update(crc, _txHeaderTo);
    *p++ = conv4to6[_txHeaderTo >> 4];
    *p++ = conv4to6[_txHeaderTo & 0xf];
    crc = _crc_ccitt_update(crc, _txHeaderFrom);
    *p++ = conv4to6[_txHeaderFrom >> 4];
    *p++ = conv4to6[_txHeaderFrom & 0xf];
    crc = _crc_ccitt_update(crc, _txHeaderId);
    *p++ = conv4to6[_txHeaderId >> 4];
    *p++ = conv4to6[_txHeaderId & 0xf];
    crc = _crc_ccitt_update(crc, _txHeaderFlags);
    *p++ = conv4to6[_txHeaderFlags >> 4];
    *p++ = conv4to6[_txHeaderFlags & 0xf];

  for (uint8_t l = len; l--;) {
    v = *buf++;
    crc = _crc_ccitt_update(crc, v);
    *p++ = conv4to6[v >> 4];
    *p++ = conv4to6[v & 0x0F];
  }
  crc = ~crc;
  v = (uint8_t)crc;
  *p++ = conv4to6[v >> 4];
  *p++ = conv4to6[v & 0x0F];
  v = (uint8_t)(crc >> 8);
  *p++ = conv4to6[v >> 4];
  *p++ = conv4to6[v & 0x0F];

  //  Now transmit the header and the payload ...
  rawSend(header, sizeof(header));
  rawSend(payload, (len + 3 + RH_ASK_HEADER_LEN)*2);
  tx(false);

  //Serial.print("CRC: ");Serial.println(crc);
}

ISR(WDT_vect)
{
  wdt_loops++;
}

// Sleep
void system_sleep() {
  cbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter OFF

  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
  sleep_enable();

  sleep_mode();                        // System sleeps here

  sleep_disable();                     // System continues execution here when watchdog timed out
  sbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter ON
}

// Setup for Watchdog
void setup_watchdog(int ii) {
  byte bb;
  int ww;
  if (ii > 9 ) ii=9;
  bb=ii & 7;
  if (ii > 7) bb|= (1<<5);
  bb|= (1<<WDCE);
  ww=bb;

  MCUSR &= ~(1<<WDRF);
  // start timed sequence
  WDTCR |= (1<<WDCE) | (1<<WDE);
  // set new watchdog timeout value
  WDTCR = bb;
  WDTCR |= _BV(WDIE);
}

void setup()   /*----( SETUP: RUNS ONCE )----*/
{
//  pinMode(LEDPin, OUTPUT);
  pinMode(LED_PIN, OUTPUT);
  led(false);

  // Initialize moisture sensor
  pinMode(MoistureSensorPinD, INPUT);

  // RF sensor initialization
  //driver.init();

  setup_watchdog(wdt_length); // approximately 8 seconds sleep

}/*--(end setup )---*/

void loop()   /*----( LOOP: RUNS CONSTANTLY )----*/
{
  if(wdt_loops >= wdt_loops_max)
  {
    //digitalWrite(LEDPin, HIGH);
    led(true);

    wdt_loops = 0;
    moisture_measurement();

    led(false);
  }
  system_sleep();

}/* --(end main loop )-- */

void moisture_measurement()
{
  // Activate sensor
  analogWrite(MoisturePowerOutPin,255);
  analogWrite(RFPowerPin,255);
  _delay_ms(150);

  // Turn On RF transmitter

  float MoistureMedian   = 0;
 // float sensorValue;
  for(int i = 0;i<=100;i++)
  {
    float sensorValue = analogRead(MoistureSensorPinA);
//    moisture_percentage = ( 100 - ( (sensorValue/1023.00) * 100 ) );
//    moistureSensorSum += moisture_percentage;

    MoistureMedian += ( 1 - ( (sensorValue/1023.00) * 1 ) );
    //delay(1);
    _delay_ms(1);
  }

  // Read digital values
  bool digitalValue = digitalRead(MoistureSensorPinD);

  // Switch off sensor
  analogWrite(MoisturePowerOutPin,0);

  // Transmit value
  TransmitSensorValue(SensorIDMoisture,MoistureMedian);

  _delay_ms(150);
  // Turn Off RF transmitter
  analogWrite(RFPowerPin,0);

}

void MessageEncrypt(int adressIn, int parameterIn, float payloadIn, byte pByteArray[])
{
  pByteArray[0] = (byte)adressIn;

  byte * payloadBArray = (byte *)&payloadIn;
  pByteArray[1] = payloadBArray[0];
  pByteArray[2] = payloadBArray[1];
  pByteArray[3] = payloadBArray[2];
  pByteArray[4] = payloadBArray[3];

  RollingCounter = RollingCounter + 1;
  if(RollingCounter > 2)
    RollingCounter = 0;

  pByteArray[5] = RollingCounter;
}

//CRC-8 - based on the CRC8 formulas by Dallas/Maxim
//code released under the therms of the GNU GPL 3.0 license
byte CRC8(const byte *data, byte len) {
  byte crc = 0x00;
  while (len--) {
    byte extract = *data++;
    for (byte tempI = 8; tempI; tempI--) {
      byte sum = (crc ^ extract) & 0x01;
      crc >>= 1;
      if (sum) {
        crc ^= 0x8C;
      }
      extract >>= 1;
    }
  }

  return crc;
}

void TransmitSensorValue(int SensorID, float SensorValue)
{
  byte MessageOut[6];
  MessageEncrypt(SensorID, 1, SensorValue, MessageOut);

    for(int i=0;i<RFRepetitions;i++)
    {
      send((const uint8_t *)&MessageOut, sizeof(MessageOut));
    }
}

The code runs like a dream as long as I use 2000 as baudrate. As soon as I use another baudrate (500 or 1000) my test receiver does not receive any messages.
Any ideas what is going wrong here?
Thanks :)

I found the problem.
I used 2 2032 battery to power the attiny85. The internal clock of the chip is not precise enough when running at 6V. To solve the issue I removed 1 battery. The alternative would be to set the baudrate of the transmitter and receiver to different values (I had to set the receiver to 520 bdps to receive the messages from the transmitter with 500 bdps).
Maybe somebody can reuse my code for his project.


text:
Is it possible to access GPIO9 and GPIO10 as DIO?
I have a nodemcu dev board with the esp12 chip. (Not the esp12e one).
I have tried to make use of gpios 9 & 10 for digital output. On the board, they are marked as SD2 & SD3. I suppose they must be serial data pins by default.
Ideally you can change the pin functions using the PIN_FUNC_SELECT() macro. So I tried the following:
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, FUNC_GPIO10);

However, on flashing this code, I notice my MCUs reboots. So it must have crashed at some point.
Am I doing this right?
PS: I was hoping to have at least 12 pins that can serve as digital output.

do you compile and flash with DOUT flash mode? btw SD label is not "serial data", but from SDIO a protocol for SDIO card (they are similar to SD card but not same).

I use platformio ide to do all the flashing

board_build.flash_mode = dout

https://github.com/espressif/esptool/wiki/SPI-Flash-Modes

Yes that seemed to make a difference. However GPIO9 still has the same problem.

with DIO set at build the mux setting should not be necessary

I am hoping we can make time and work together and nail this. Join here and mention availability: https://chat.stackexchange.com/rooms/110184/nodemcu-users

sorry, I don't know what else you could try. and I don't have a NodeMcu. other esp8266 boards and modules don't break this pins out. so I never tested this.


text:
Power Arduino and LED strip
I saw this question about powering Arduino and LED strip. So, I searched for a 5v 4a power supply and foud this one.
How does that adapter provide power for both Arduino and LED strip? I thought I might need DC barrel Plug to alligator clips but I'm not sure as this is the first time I use an external power supply to power multiple components.
So what do I need to make that wall adapter able to power both Arduino and LED strip?

does it provide enough current to power both? ... just sum the current requirement of all of the components

@jsotola I mean the 4A is enough, but when using the DC barrel plug to alligator clips will it still be 4A?

that is not what you asked .... if you meant to ask something different, then edit your post

I assume, that your problem is how to connect everything to the power supply.
You have some different options, depending on your requirements. The linked adaptor (barrel plug to alligator clips) doesn't seem to fit the barrel plug of the power supply. So you cannot use that. Especially it seems, that both are the male part of the connection. For every plug connection you need a male and a female part of the same connector type (much like your power outlet on the wall is a female part, while the power plug on your supply is a male part; in terms of plug systems).

The best way (especially, when you want to not only experiment, but also use it as a fixed product) would be to solder the wires. For this you need a soldering iron, soldering tin and something to clean the iron (sponge for soldering irons for example).

You can buy a barrel jack, solder wires to it and connect them to the Arduinos 5V pin, ground and to the LED strips power lines in parallel (from + pin of the supply one wire each to 5V Arduino and + pin of the LED strip, from - pin of the supply one wire each to ground of Arduino and - pin of the LED strip). Then you can still disconnect the power supply from your project.
If you don't want to buy a barrel jack and you don't need to disconnect the power supply from your project, you can splice up the cable of the power supply (only the LOW VOLTAGE PART!!!). You can use nail scissors, if you don't have other tools for it. Cut off the plug by cutting the cable a few cm before it. Then cut the plastic between the 2 connected parts of the cable for a few cm, so that you get the 2 individual cables (+ and -).  Use the scissors to carefully cut the outer plastic around the cables and remove about 1cm of it, so that you now have 2 cable ends with the bare cable core free. Twist each end, so that it each little copper strand stays in the cable shape. Then solder the cable ends. Now you can take another wire/cable to solder the connections from the two ends to the described parts. Be sure to isolate the connections at the cable (in the best case with shrinking pipes, otherwise you can also use tape).

If you don't want to solder, you can search for fitting connectors for every part. There are breadboard power adaptors, which should work with this power supply. They have pins on them, that you can not only use with breadboards, but you can also connect jumper wires to them. There also exist such adaptors for typical LED stripes, though that depends on the type of strip, that you have. When looking for jumper wires, you should make sure, that they are capable of conducting enough current. The Arduino does not need much current, thus standard jumper wires will be sufficient. But the LEDs can draw much more current, so that the standard jumper wires will start to smolder and catch on fire. Then you need some with a bigger wire diameter.

You can also use alligator clips, but in my experience, they only work for rather specific cases. The connection, that they make, is fragile and can be easily disturbed. They are slipping and rotating easily. When connecting the LED strip, you might easily connect + and - together and destroy the power supply. Also it is almost impossible with most of them to connect to a standard 0.1 inch pin (which are used on the Uno and Nano), without also connecting other pins. Unless you break out these pins with something else (like jumper cables), that is not a good choice.

You can now choose yourself, which way to go. If you plan to do more with Arduino and electronics, I would suggest, that you buy a soldering iron and the needed supplies. You will need it and they only cost a few bucks, if you just buy a simple one (back then I got one for 15€/$, which also had a temperature control, so you can also get it cheaper). If you don't want to buy it, but still want to solder, you could look for a maker space near your location.
I would go for soldering here, because you are very much limiting yourself, when you choose to do not. Then you need to buy fitting parts, which is more difficult.

how do I know what the ground is and the 5v?

For the power supply you can see it on the label. There you will find the following sign:

It means, that the outer shell of the connector is ground (-) and the inner pin is 5V (+). With cables there are 2 possibilities:

Often the wires inside a cable each have an own isolating plastic shell around them, which is color coded. Black is normally ground, while red is 5V/+.

When having a 2 wire cable, the cable is often designed as coaxial cable (which reduces noise on the signal). In that case you have one inner wire, which has it's own isolating plastic shell, and the outer wire, which is laid around the inner wire without any further isolation. The outer wire is normally ground.

When using an extra cable for connecting 2 parts, make sure to use the same wires on both sides (for example the red wire for 5V on both sides).
To be sure, you can check the voltage on the wires with a multimeter (also a very useful tool), when the cable is connected. A multimeter has a positive and a negative lead, which are marked as red and black respectively. When you connect the multimeter to the wires and it shows a positive voltage, you have found the correct association of the wires with their voltage (5V or ground).

Thanks for your answer. That is exactly what I wanted to know. I'm going for the first option but I don't understand where I solder the wires on? For example, I have this one: https://www.adafruit.com/product/327 how do I know what the ground is and the 5v? With the aligator clips it was quite easy to see.

@Helper I added a description about how to find the correct polarity.+

You can feed 5V directly into the 5V pin of the Arduino as ChrisL says. However, that bypasses the protection circuits built into the Arduino. If you ever forget to disconnect the 5V and plug a USB cable into your Arduino then you risk damaging it, since both your external power supply and the USB port will be feeding 5V into the 5V line.
What I decided to do is to cut the end off of USB cable and connect that to my 5V power supply. On almost all USB cables, the +5V wire is red and the ground wire is black. You'd just solder red to +5V and black to ground, then plug the USB cable into your Arduino. Then when you need to connect the Arduino to your computer, you disconnect the USB power cable and plug in a USB data cable. It's impossible to feed power from both sources at once.
If you're going to be doing much tinkering with Arduinos and electronics you should get a decent soldering iron and an auto-ranging multimeter. You can use the multimeter to figure out which wires are which. (See chrisl's on how to use a multimeter to find positive and negative power connections.
Another issue you may face is voltage droop on your power supply as your LED strip turns groups of LEDs on and off. If you draw near the max current from your power supply then there will likely be fluctuations in the power supply voltage as the LEDs turn on and off.
What are the max current requirements for your LED strip? You don't want to draw too close to the full output of your power supply or you might get fluctionations in voltage that could cause your Arduino to malfunction. If you use a power supply with something like 25% extra capacity (Say your LED strip draws 4A and you use a 5A power supply instead) you should be ok.

For the wall adapter, I think to get 5 V  (DC) 4 A, the LEDs 30 will take 50mA so that gives 1.5A, if I ever change to 60 led (3A) then I'm still safe.


text:
Unable to connect PN532 Board to Arduino Uno
I'm attempting to connect this PN532 NFC Board to an Arduino UNO using SPI. Currently my arduino is unable to recognize the board and I'm not sure whats the root of my issue. I'm using the Adafruit PN532 library and my program fails at trying to get the Firmwarm Version of the attached chip. I've attached the code and pictures of the soldering and connections. One interesting note is the LED on the chip will turn on before I connect VCC. The LED will turn on as soon as plug in MOSI (Not sure if that is intended behavior). Any ideas on where my issue might be?
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_PN532.h>

// If using the breakout with SPI, define the pins for SPI communication.
#define PN532_SCK  (13)
#define PN532_MISO (12)
#define PN532_MOSI (11)
#define PN532_SS   (10)

// Use this line for a breakout with a SPI connection:
Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS);

void setup(void) {
  Serial.begin(115200);
  nfc.begin();
  uint32_t versiondata = nfc.getFirmwareVersion();
  if (! versiondata) {
    Serial.print("Could not find board");
    while (1); // halt
  }

  Serial.print("Found Board");
  nfc.SAMConfig();
}

void loop(void) {
  uint8_t success;
  uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };
  uint8_t uidLength;

  success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);

  if (success) {
    Serial.println("Found a card");
    }
    delay(2000);
}

MOSI pin and IRQ pin looks badly soldered ... could also be a reflection in a very good solder connection

you use the constructor for software SPI. use Adafruit_PN532 nfc(PN532_SS);. the SPI library knows the other pins


text:
Digital Pin won't ground when set to LOW
My friend and I are repurposing an old rc car for a project. When we connect the dc motors to 5V and ground, the motors spin. However, when we power the motors from 5v and ground it in the digital output pin set to LOW, nothing happens. The identical circuit works in tinkercad. We are using a nano, but have tried an uno and mega as well.

you possibly destroyed the arduino output pin

An output pin can't handle that sort of current.  I would suggest you do some reading on Ardunio and motors.  If you google as much you'll be hit right off the bat with the idea of a motor driver since the pins can't drive motors by themselves.  You've probably damaged your Arduino now.

The pin still works with leds and a small dc motor

there is a lot of info about driving motors on this site

You shouldn't try to source or sink more than 20 mA from an Arduino pin. The absolute max is 40 mA, but 20 is the recommended limit. Also you should never hook an inductive load directly to an Arduino pin. When you disconnect an inductor from power, there is a large reverse rush of current as the magnetic field collapses. This is known as back-EMF, and even if you don't exceed the current limits of a pin, the back-EMF may fry the pin, or the entire board.

Never directly connect a motor to an Arduino IO pin
You will destroy the Arduino.
An Arduino cannot source (or sink in your case) enough current to drive a motor, and if the motor did manage to turn the huge amounts of EMI it generates would literally blast holes in the silicon inside the chip.
You must use a motor driver of some form. If you only want one direction that driver can be a single NPN Bipolar transistor or N-channel MOSFET.  If you need it to change direction then an H-bridge is what you want.

Thanks. We ended up using a relay in the meantime

To the OP: If you do end up powering your motors with transistors, make sure to add a "flyback diode" to protect the transistor from back EMF. (This is a suitably rated diode wired backwards across the motor terminals. They're needed for any inductive load, not just motors.)

Use that diode for the relay, too. As it is an inductive load, it will generate flyback spikes when switched off.

Good point on the relay. I assumed the OP was using a "digital relay module" which has a transistor, diode, and usually an optic-isolator built into it.


text:
Burning Digispark bootloader without an Arduino
I've been wondering if there is any method to burn a Micronucleus bootloader into a blank ATtiny85 Digispark using just Windows or a Linux distro, and not needing another Arduino board such as UNO that acts as ISP.

it will be hard even with programmer or other Arduino. only other option is a wiring on computers parallel connector. but most new computers don't have it.

I've found some guides about how to burn the bootloader using an UNO and the process doesn't seem to be very hard, my trouble here is that i don't have an UNO at the moment so i'm looking for alternative ways to do it. Could you explain which would be the way to go using a parallel connector?

the Digispark doesn't have reset pin. that will be a complication

https://www.instructables.com/id/Simplest-AVR-Parallel-port-programmer/

Here are some more simple programmers (including serial port, which may be easier to find).

it crossed my mind that a USB keyboard has three outputs ... a quick search found this ... https://hackaday.com/2012/11/26/usb-keyboard-becomes-an-avr-programmer/

@Vile Did you managed to burn the bootloader using the Arduino? I ran into the same issue.


text:
if I add a .cpp file, Serial becomes unusable
I am using the mega 2560. When I just use .ino and .h files, if I use Serial, it works fine, without even using:
#include <SoftwareSerial.h>

However, when I add a .cpp file I start getting 2 errors, one is solved by adding the aforementioned include, the second one, after adding it, is :
'Serial' was not declared in this scope

I know I can declare it manually and use the RX/TX pins, but I would like to be able to use the default Serial so that I don't have to occupy more pins. Especially since it works file w/o the .cpp file. Can anyone explain to me why this happens? Is it because I specify a C++ file so the compiler changes?

A CPP file isn't an Arduino file. It doesn't know about anything Arduino-esque unless you tell it about it.
The simplest way is to just add, at the top of the file:
#include <Arduino.h>

Ah, damn once you say it it becomes so obvious, thank you.


text:
What does display.setSegments(&segto, 1, 1); do?
I am using a TM1637 display for my Arduino Uno. The goal was to just light up one point of the colon in the middle - what seems to be kind of impossible to accomplish. During research I stumbled over the following snippet, which I dont fully understand:
  uint8_t segto;
  int value = 1244;
  segto = 0x80 | display.encodeDigit((value/100)%10);
  display.setSegments(&segto, 1, 1);

Ok line 1 seems to declare s.th. like a char, an unsigned 8bit integer. Line 2 should be clear.
Line 3: The pipe symbol seems to do a kind of addition - never seen this before. The rest here is also not clear to me - why these strange calculation to pass a value (here 2) to .encodeDigit() ?
Finally line 4: Why is the adress of 'segto' passed to the function instead of just the value?
This all ends up showing a "2:" on the display. I got the snippet from this 'manual': https://robojax.com/learn/arduino/robojax-TM1637_display_manual.pdf
Maybe s.o. can help to light things up a bit

Let's take the hardest line first.  We'll start from the "inside" outwards.
segto = 0x80 | display.encodeDigit((value/100)%10);

The innermost bit is:
value/100

That gives you 12 from 1244.
Then there's modulus 10.
12%10

That gives you 2 (divide by 10 and return the remainder - 12/10 = 1.2, or 1 remainder 2)
That is then passed through a function that calculates what segments need to be turned on to represent the digit 2. Let's say that's 00110111 in binary, where each bit represents a segment to display.
To that you want to add the colon, which is in the most significant bit's place.  So you set that bit. That's done with the OR operator, which in C is |. 0x80 is 10000000 in binary.
OR the two values together:
00110111
10000000
========
10110111

That value is then assigned to the segto variable.
I am not familiar with that library, but I would assume that the setSegments function is expecting an array of segment settings, a number of digits to apply it to, and maybe a digit offset in the display (at a guess).
In C there is no real difference between using a 1 element array and using a variable and taking its address.
You could just as well have used:
uint8_t segto[1];
int value = 1244;
segto[0] = 0x80 | display.encodeDigit((value/100)%10);
display.setSegments(segto, 1, 1);

If you were doing more than one digit you'd be wanting to use an array anyway.


text:
GPS date and time not displaying correctly in Arduino Uno,NEO6M GPS module
I am learning how the Arduino and GPS module work so I can apply it to another project.
My components are an Arduino Uno, NEO-6M GPS module, and a Adafruit 1.8" TFT display.
The code did not work as expected.  It does display "waiting for sats".
However, it still displays the generic time and date, 1-1-1970 and 12:00:00 AM, for a while until the local time adisplays.
Plus the updated code takes a lot longer to display the time
Here is the code so far.  What I would like it to do is:

Display "waiting for sats"
continue when a successful GPS signal is received
adjust GPS time & date to local
display date and time

Eventually this will be the basis for a Speed and GPS trackker for my RC vehicles.
Any help is greatly appreciated.
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <TimeLib.h>

#define cs   10
#define dc   8
#define rst  9

#include <TinyGPS++.h>
#include <SoftwareSerial.h>
Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst);

static const int RXPin = 2, TXPin = 3; //GPS communication

// Change this value to suit your Time Zone
const int UTC_offset = -4;   // Eastern Australia Time is 10

static const uint32_t GPSBaud = 9600;

TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);

time_t prevDisplay = 0; // Count for when time last displayed

void setup()
{

  Serial.begin(9600);  //set baud rate for serial monitor
     ss.begin(GPSBaud);  //set baud rate for GPS

   tft.initR(INITR_BLACKTAB);     //correct INITR for my display

  tft.fillScreen(ST7735_BLACK);
  tft.setCursor(20, 58);
  tft.setTextSize(1);
  tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
  tft.println("GPS Date & Time");
  tft.print("        Monitor");
  delay(3000);
  tft.fillScreen(ST7735_BLACK);
}

void loop()
{

  tft.setTextSize(1);
  tft.setTextColor(ST7735_GREEN,ST7735_BLACK);

     if (ss.available() < 1)
{
       gps.encode(ss.read());
 }

        GPS_Timezone_Adjust();  // Call Time Adjust Function

}

void GPS_Timezone_Adjust(){
  while (ss.available() > 0) {
    gps.encode(ss.read());
    if (gps.location.isUpdated()) {

      int Year = gps.date.year();
      byte Month = gps.date.month();
      byte Day = gps.date.day();
      byte Hour = gps.time.hour();
      byte Minute = gps.time.minute();
      byte Second = gps.time.second();

//Hour = hourFormat12();
        // Set Time from GPS data string
        setTime(Hour, Minute, Second, Day, Month, Year);
        // Calc current Time Zone time by offset value
        adjustTime(UTC_offset * SECS_PER_HOUR);

    }
  }

  if (timeStatus()!= timeNotSet) {
  if (now() != prevDisplay) {
      prevDisplay = now();
      ClockDisplay();
    }
 }
}

void ClockDisplay(){
    tft.setCursor(5, 8);

    tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
    tft.print("Date:   ");
    tft.setTextColor(ST7735_CYAN,ST7735_BLACK);

      if(month() < 10){
        tft.print("0");
        }
      tft.print(month());

      tft.print("-");

      if(day() < 10){
        tft.print("0");
        }
      tft.print(day());

      tft.print("-");

      tft.print(year());

    tft.setCursor(4, 30);
    tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
    tft.print("Time:   ");
    tft.setTextColor(ST7735_CYAN,ST7735_BLACK);

      if(hourFormat12() < 10){
        tft.print("0");
        }
    tft.print(hourFormat12());
    tft.print(":");

      if(minute() < 10){
        tft.print("0");
        }
    tft.print(minute());
    tft.print(":");

      if(second() < 10){
        tft.print("0");
        }
    tft.print(second());

    if (isAM()) {
    tft.println(" AM ");
    } else {
    tft.println(" PM ");
    }

    tft.setCursor(5,50);
    tft.setTextColor(ST7735_WHITE,ST7735_RED);
    tft.println("RAW GPS DATE & TIME");

    tft.setCursor(5,58);
    tft.print(gps.date.month());
    tft.print("-");
    tft.print(gps.date.day());
    tft.print("-");
    tft.print(gps.date.year());

    tft.setCursor(5,66);
    tft.print(gps.time.hour());
    tft.print(":");
    tft.print(gps.time.minute());
    tft.print(":");
    tft.print(gps.time.second());

  smartDelay(400);
  }
    // deadline for a good recption
      static void smartDelay(unsigned long ms)
  {
  unsigned long start = millis();
  do
  {
    while (ss.available())
      gps.encode(ss.read());
  } while (millis() - start < ms);
}

Display "waiting for sats" ... continue when a successful GPS signal
is received

You are (or the Arduino library you are using is) using the time.h library which starts on January 1st, 1970.  If no adjustments are made, time.h will report January 1st, 1970.
You are not (or the Arduino library you are using is not) waiting for a "good GPS signal" indication from the GPS module before displaying the time.

adjust GPS time & date to local

If you are using time.h you (or the Arduino library you are using) should set a time-zone offset instead of correcting the time by hand.  This will take advantage of the time.h library utilities which take care of troublesome cases like calculating a time & date which crosses midnight with respect to UTC (aka GMT).

display date and time

The time.h library stores the date / time as the number of seconds since January 1st, 1970.  So when displaying the current time, use time.h function calls to convert this counter to the current local time.
Hints / Suggestions:

The GPS module is a radio receiver.  It works best when the view of
the sky is unobstructed by buildings, trees, hills or bad weather.
Such obstructions results in slow lock times or no lock at all.  The
more satellites the GPS module can see the better.
The GPS module is a computer in and of its self.  The computer will
analyze messages form satellites several times before it is ready to
report location and time data.  If possible, leave the GPS module
powered up even if the Arduino is not.  This should likely reduce or
eliminate the delay the GPS module needs before  reporting location
and time.

Added later...
@Tvr4 brings up a good point.  While time.h is more ubiquitous (used almost everywhere in C programming), in the Arduino paradigm, the built in Arduino time library is often used.  For more, this is discussed in this stackoverflow question / answer.  If you want to dive into the Arduino time library, the code is in this github repository.  Also, you should find more help with this time libaray in the readme file displayed on that web page.

timeStatus() is part of the TimeLib
Here is the page on the library
https://playground.arduino.cc/Code/Time/

...thanks.  Added additional text to the answer according to you suggestion.

I'm guessing that the GPS module doesn't receive a time reading until it acquires a GPS lock. That can take many seconds.
You haven't posted your code so we can't tell how you're handling the time reading.
I would suggest checking for the midnight 1970 time (which is the UNIX "epoch time") and handling that with special-case code. If you're reading the time as a numeric value it is almost certainly 0.

I am wondering if the problem is with this part of the code
if (timeStatus()!= timeNotSet)
{
if (now() != prevDisplay)
{
prevDisplay = now();
ClockDisplay();
}
}

what library defines the function timeStatus()? You need to tell us what libraries/frameworks you are using.


text:
Adding SIMCOM SIM 900A to Arduino Fire Fighter Robot for sending alert messages
I had made Arduino Fire Fighter Robot. I want to add SIMCOM SIM 900A GSM module to Arduino. When flame sensor will detect fire then " Fire!!!" message will be sent to mobile phone and when fire is extinguished then " No fire!!" will be sent to mobile phone. So  how can I add the part of SIMCOM SIM 900A GSM in my project?
Here is the code:
 #include <Servo.h>

Servo myservo;

#include <LiquidCrystal.h>

LiquidCrystal lcd(30, 31, 32, 33, 34, 35);

#define Left_S       9                       // left    sensor
#define Right_S      8                       // right   sensor
#define Forward_S   23                       // forward sensor

#define LM1         52                       // for pump motor
#define LM2         53                       // for pump motor

#define IN1          5                       // for motor
#define IN2          4                       // for motor
#define IN3          3                       // for motor
#define IN4         22                       // for motor

int LEDR     = 36;                           // for danger signal
int LEDB     = 37;                           // for safe signal
int buzz     = 38;                           // for led or buzzer
int pos      =  0;
int Contrast = 20;                           // for adjusting the brightness of the LCD , 20 is selected for the contrast of LCD

boolean fire = false;

void setup() {

    analogWrite(6, Contrast);

    lcd.begin(16, 2);

    pinMode( Forward_S         , INPUT  );
    pinMode( Left_S            , INPUT  );
    pinMode( Right_S           , INPUT  );

    pinMode( LM1               , OUTPUT );
    pinMode( LM2               , OUTPUT );

    pinMode( IN1               , OUTPUT );
    pinMode( IN2               , OUTPUT );
    pinMode( IN3               , OUTPUT );
    pinMode( IN4               , OUTPUT );

    pinMode( buzz              , OUTPUT );

    pinMode( LEDR              , OUTPUT );
    pinMode( LEDB              , OUTPUT );   // xxxxxxxxxxxxx        duplicate

    myservo.attach(25);
    myservo.write(90);
}

void put_off_fire() {

    delay (500);

    digitalWrite(IN1, HIGH);
    digitalWrite(IN2, HIGH);
    digitalWrite(IN3, HIGH);
    digitalWrite(IN4, HIGH);

    digitalWrite(LM1, HIGH);
    digitalWrite(LM2, LOW );
    delay(500);

    for (pos = 50; pos <= 130; pos += 1) {
        myservo.write(pos);
        delay(10);
    }

    for (pos = 130; pos >= 50; pos -= 1) {
        myservo.write(pos);
        delay(10);
    }

    digitalWrite(LM1, LOW);
    digitalWrite(LM2, LOW);

    myservo.write(90);                       // xxxxxxxxxxxxx        duplicate

   fire = false;                            // xxxxxxxxxxxxx        not needed
}

void loop() {

    myservo.write(90);                       // xxxxxxxxxxxxx        duplicate
//  Sweep_Servo();

    lcd.setCursor(0, 1);

    fire = true;                             // preset the state (gets cleared when no fire is detected

    if (digitalRead(Left_S) == 0) {          // If Fire is left ahead

        lcd.print("Flame on Left");

        digitalWrite(IN1 , LOW);            // Move the robot left
        digitalWrite(IN2 , HIGH );
        digitalWrite(IN3 , HIGH);
        digitalWrite(IN2 , LOW );
    }

    else if (digitalRead(Forward_S) == 0) {  // If Fire is straight ahead

        lcd.print("Flame on front");
         digitalWrite(IN1 , LOW);            // Move the robot right
        digitalWrite(IN2 , HIGH);
        digitalWrite(IN3 , LOW);
        digitalWrite(IN4 , HIGH);

           }

    else if (digitalRead(Right_S) == 0) {    // If Fire is to the right

        lcd.print("Flame on Right");

        digitalWrite(IN1 , HIGH);            // Move the robot right
        digitalWrite(IN2 , LOW);
        digitalWrite(IN3 , LOW);
        digitalWrite(IN4 , HIGH );
    }

    else {                                   // fire was not detected by any of the sensors

        fire = false;

        lcd.print("No flame");

        digitalWrite(IN1 , HIGH);            // Do not move the robot
        digitalWrite(IN2 , HIGH);
        digitalWrite(IN3 , HIGH);
        digitalWrite(IN4 , HIGH);
    }

    delay(300);                              // Slow down the speed of robot

    if (fire) {

        digitalWrite(LEDR, HIGH);            // do fire lights
        digitalWrite(LEDB, LOW);
        digitalWrite(buzz, HIGH);

        put_off_fire();
      //  delay(100);
    }

    else {

        digitalWrite(LEDR, LOW );            // do nofire lights
        digitalWrite(LEDB, HIGH);
        digitalWrite(buzz, LOW );

    }
}

What is your actual problem in doing so? Have you googled for tutorials about the SIM900 and have you tried some example codes, to learn how it works? There are tons of information about the SIM900 out there

I have tried but I couldn't. I bought SIMCOM SIM 900 module which supports 2G SIM but 2G SIM is no longer available in our country. Then I bought SIMCOM SIM900A but I couldn't connect the GSM module with the above code though I saw many examples. And there are various types of circuit of SIMCOM SIM 900A. Which one should I follow? That's why I am facing difficulty in adding the part of sending alert messages with the above code.

If this is a school project, why not try something where you control all the radio equipment.  Such as LORA?  This may simplify your efforts and code.  If this is a one-off project (you are not sensitive to cost), why not try to use a cell phone as a gate-way to an existing cell phone network.

Thanks for your suggestion. As I had already submitted the concept paper of my project, so there is no scope of changing the concept paper and I have to use SIMCOM SIM 900A module.

As I remember the SIM900A is interfaced via Serial (UART), which means, that no big circuit is involved. Just power supply and RX and TX pins connected. What types of different circuit have you seen? Can you provide links to show, what caused your confusion about the circuit?