text:
Combining ADC IRQ with SPI peripherals results in SPI not working
I'm working on a pet project that requires ADC, SD card (SPI interface, SdFat library) and a display in the future (also SPI).
I have put together a piece of code that initializes ADC at the highest clock frequency and uses ADC_IER_DRDY interrupt and double buffering.
I have also put together a piece of code based on one of SdFat examples that inits SD card and benchmarks its speed.
On its own, each piece works just fine. But combined together, it breaks if I enable the ADC interrupt. It causes SdFat to stall, not sure where (I don't have a debugger). Simply disabling the interrupt is enough to let SdFat work just fine, but I need both. I have also set ADC IRQ priority to 0 and most other IRQs to 1, but removing NVIC_SetPriority calls does not solve the problem.
Any advice on how to make both ADC and SPI work, with ADC IRQ priority so that I don't miss samples?
I also tried lowering SPI speed from full to 1/16th (SdFat lib has a convenient parameter for this), didn't help.
The code is not long, but a bit too much for inlining into the question, here are Github links.

main.cpp and ADC stuff - just commenting the highlighted line fixes SPI.
SD card stuff. Of note: sometimes it prints "chipselect: 10", sometimes not even that.

Update: making ADC handler empty does not resolve the problem, neither SPI nor printing to Serial works.

First thought was to poll the ADC and not use interrupts.  But if you need it that fast, well.  My second thought is to rewrite the interrupt routine to handle both the ADC and the SPI.  Guessing, only the last feature you instantiate is working.  Are you setting up the ADC after you setup the SdFat?

@st2000: no, I'm setting up ADC first, then running SdFat code. If ADC interrupt is enabled by now, SD doesn't work. I don't have any sort of explicit SPI interrupt handling routine, it's either part of the SdFat lib or the Arduino framework itself, not sure yet.

My ADC interrupt can't be taking more than 30 cycles, I don't understand why it affects SPI in the first place.

@st2000: I made ADC handler body empty, but still neither SPI nor printing to Serial works. Is that supposed to happen? Any ideas why this might be?

These types of problems can take a lot of digging to solve.  Ideally, you would find someone who has solved this exact same problem.  The rest of us, with out a considerable investment in time, can only make suggestions.  If interrupts are involved for both the ADC and SPI features, and if the embedded processor you are using only has 1 interrupt vector for both, then I sill think the vector is being over-written pointing to just the interrupt routine of the last feature to modify the vector. If true, then rewriting that interrupt routine to handle both features may be a solution.

Some other suggestions: 1. Arduino platforms are cheap.  Use one for the ADC and another for the SPI.  2. Try a larger embedded processor.  Different processor have different hardware features.  Maybe you will get lucky and the libraries will be compatible on a different embedded processor.  3. Try a different library.  People write the libraries and it is highly unlikely any 2 approach the problem identically.

@st2000: I understand, appreciate the suggestions. I'm sure this is doable in principle, I'll keep digging and will post an answer if I find a solution.


text:
Compile error in Ubuntu 18.04
I'm trying to compile a code to arudino pro micro, I have the right option for compiling like the port and the type of the board,but I get an error,I can't copy

did you start with Arduino on Linux now? did it ever work? did you set the access right to USB port?

Welcome to Arduino Stack Exchange. you have a issue about include <keyboard.h> . What your the library using?

I open arduino ide using ubuntu,this is my first time compile a code in linux

then please read the "Please read" for Linux https://www.arduino.cc/en/Guide/Linux#toc6

And I believe I chose the correct port

Did you join the dialout group as instructed in the guide?

post your code in proper tags, not an image.  Please read Arduino SE tour if you don't know how.

This is likely a permission problem.  The user likely does not have permission to read from and write to the port created when plugging in the Arduino.  This can be temporally fixed using the following command:
sudo chmod 666 /dev/ttyACM0

However, this procedure is only temporary as the port is recreated every time the Arduino is reconnected to the computer.  And upon recreation the permissions are reset to their defaults for security reasons.
A better solution is to determine the group which the port belongs to and to add the users expected to access these connected devices to that group.
Plugin and list the port to determine its group:
ls -l /dev/ttyACM*

or
ls -l /dev/ttyUSB*

The group the ports belong to will likely be "dialout".  Add the user to that group:
usermod -a -G dialout user_name

...where user_name is replaced by the name of the user who needs access to the port.  If you don't know the name of the current user you can use this command:
whoami

Sorry for the late reply,it worked in the ide that I download from the web,apparently ide from the ubuntu software won't work.
Thank for the answer

It's not the new IDE. It's the setup script that comes bundled with it that issues the usermod command suggested by st2000.

source: Stack Exchange

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

sort: votes


text:
about how to write data in the whole EEprom?
I have interfaced AT24c1024 EEprom with ATmega32.AT24c1024, which has 512 pages each of 256 bytes. There are two mode of writing (byte write and page write).
In page write mode, it is capable of writing 256 bytes for page; if we want to write 258 bytes, then the first two bytes in the beginning of that page will be overwritten.
My question is: what should I do to write in the whole EEprom (i.e) if I want to write 300 bytes, I want to writes 256 bytes in a page then continues to the next page and so on?

In that case you write two pages, the first page containing the first 256 bytes and the second page containing the following 34 bytes.
You can do a speed check to see if writing the second page's 34 bytes by using the byte write is faster, but I doubt that.
In case you want to keep from the second page the remainder of the 34 bytes (the 256-34 bytes following), you first read the second page, than you change the first 34 bytes, than write it back.
Also note that there is a limit on the number of writes on a page. This is called page wearing. So if you write these 2 pages very often, you might want to come up with an algorithm to rotate through all the available pages in your EEPROM, and not writing every time to the same 2 pages.
EXAMPLE
Assume you want to write totalBytesToWrite:
// Calculate the number of pages to write, round up.
int pagesToWrite = int((totalBytesToWrite + 255) / 256;

for (int page = 0; page < pagesToWrite; page++) // Current page to be written
{
    // Calculate number of bytes to be written in this page, for the last page, write remaining bytes, otherwise 256
    int pageBytesToWrite = (page == pagesToWrite - 1 ? totalBytesToWrite % 256 : 256;

    // Write page (btw, I do not know what the second argument char deviceAddress means)
    page_write(n / 256, ??, &memory[n], pageBytesToWrite);
}

Dear sir,I want to use the page write mode,when I use it  to write 300 byte,it will write the first 256 bytes in that page and then overwrite the first 34 bytes in the same page to write the rest 34 bytes....my question..how to continue to write these 34 bytes in the next page?

If you overwrite the 34 bytes in the same page you lose the before written 256 bytes (is that what you want?) ... in the function for writing data to the page I guess there is a page number, can you give the link of the API (functions) for that EEPROM (the library you use) ?

The function containing the staring address you want to write from...

To write 'to' you mean?

The address you want to start  writing data from it

Can you give me a link to the library you use?

void  page_write(unsigned long starting_memory_address, char device_address,char x[],int len){
unsigned long temp;
temp=starting_memory_address>>8;
temp >>=8;//remaining is P0
twi_start();
twi_write_address(device_address|(((unsigned char)temp)<<1));
twi_write_data(starting_memory_address>>8);
twi_write_data(starting_memory_address);
for(int i=0;i<len;i++) {twi_write_data(x[i]);
_delay_ms(10);}
twi_stop();
}

So I guess starting_memory_address should be set to 0 when writing to the first page, and 256 when writing to the second page ... the documentation of the library should tell in more detail.

Does that mean that I should make a condition if the number of bytes is more than 256 then the starting_memory_address should be incremented by 255?

I would make a for loop, iterating through each 256 bytes and write page by page incrementing the address to write to (on the EEPROM) and the source memory (data you want to be stored) by the same iterator value.

OK..could you write me a simple pseudo code for this ...thanks

I tried (but cannot check it since I don't have the library nor the EEPROM).

Thank you sir....I am very thankful for you......my regards...

You're welcome ... you can upvote and accept the answer if it helped please. (next to my answer is a digit (0) and an up and down arrow. By clicking the up arrow you upvote an answer (meaning it's helpful), or downvote (if it's a bad answer). In case of multiple answers, you can 'accept' one answer that solves your problem, by clicking the 'accept answer' button (or some similar text).

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


text:
MKR1000 disconnecting when hooked up to RGB 16x32 LED Matrix
This tutorial is from 2012, before the MKR1000 existed. The tutorial says the 16x32 LED Matrix panel is compatible with the Arduino Zero, which the MKR1000 is supposedly related to, so I'm thinking I should be able to upload the same program. However, the board keeps disconnecting every time I try to upload a simple sketch, so I am worried that perhaps they are not compatible. I am using the same wiring as the Arduino Uno (using pins 2-10, A0, A1, A2, GND on the MKR1000) that you can see in this tutorial

without anything wired to pins is it OK with upload?

Yes, for example I am able to upload the "Blink" program just fine.


text:
Arduino Communication with Sim 900
Im using an arduino uno and a sim 900, the simcard is setup and working as I can make a phone call to it and it rings.
The sim 900 is powered via the power jack and the uno is currently powered using USB.
I am trying to print out incoming text messages however with serial monitor open I only see "Initialising...".
    #include <SoftwareSerial.h>

//Create software serial object to communicate with SIM900
SoftwareSerial mySerial(7, 8); //SIM900 Tx & Rx is connected to Arduino #7 & #8

void setup()
{
  //Begin serial communication with Arduino and Arduino IDE (Serial Monitor)
  Serial.begin(9600);

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

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

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

  mySerial.println("AT+CMGF=1"); // Configuring TEXT mode
  updateSerial();
  mySerial.println("AT+CNMI=1,2,0,0,0"); // Decides how newly arrived SMS messages should be handled
  updateSerial();
}

void loop()
{
  updateSerial();
}

void updateSerial()
{
  delay(500);
  while (Serial.available())
  {
    mySerial.write(Serial.read());//Forward what Serial received to Software Serial Port
  }
  while(mySerial.available())
  {
    Serial.write(mySerial.read());//Forward what Software Serial received to Serial Port
  }
}

I cant for the life of me figure out why its not printing anything else out? Can anyone give me any guidance or what to check?

Check out https://arduino.stackexchange.com/q/13683/19409

I think I see on the shield jumpers to use it over SoftwareSerial even if it is on the Uno

The 'Initializing' printout happens because that is sent directly to the UNO's hardware serial port.  The rest doesn't happen because it is directed to the SIM card via SoftwareSerial pins 7 & 8, and the SIM card apparently isn't responding.
Cut the problem in half:  Connect pins 7 & 8 together, and run your program again.  If you get "AT" and the rest, then you know the 'MySerial' port is active and working correctly, and the problem is in the SIM 'half'.  Maybe you have an incorrect wire connection there, or maybe the SIM card's default serial rate isn't 9600, or something like that.  YMMV ;-).
As a test, I ran your program on a UNO, with a jumper wire between pins 7 & 8.  Unfortunately this did not work, but now I knew that the problem had nothing to do with the SIM shield. The result wasn't what I expected, but now I had 'cut the problem in half'.
Now that I had determined that the SIM card wasn't a factor (so far, anyway), I could concentrate on the 'UNO half'.  After some web research I found that 'Software Serial' doesn't support 'loopback' (looping the transmit line back into the receive line) because it cannot simultaneously transmit and receive.  Fortunately, the 'AltSoftSerial' library by Paul Stoffregen does support simultaneous transmit & receive, and so will support loopback.
So, I installed the library on my Arduino setup, and compiled and uploaded the example shown below.
#include <AltSoftSerial.h>

// AltSoftSerial always uses these pins:
//
// Board          Transmit  Receive   PWM Unusable
// -----          --------  -------   ------------
// Teensy 3.0 & 3.1  21        20         22
// Teensy 2.0         9        10       (none)
// Teensy++ 2.0      25         4       26, 27
// Arduino Uno        9         8         10
// Arduino Leonardo   5        13       (none)
// Arduino Mega      46        48       44, 45
// Wiring-S           5         6          4
// Sanguino          13        14         12

AltSoftSerial altSerial;

void setup() {
    Serial.begin(9600);
    //while (!Serial); // wait for Arduino Serial Monitor to open
    Serial.println("AltSoftSerial Test Begin");
    altSerial.begin(9600);
    altSerial.println("Hello World");
}

void loop() {
    char c;

    if (Serial.available()) {
        c = Serial.read();
        altSerial.print(c);
    }
    if (altSerial.available()) {
        c = altSerial.read();
        Serial.print(c);
    }
}

After uploading the code, I 'looped' pin 9 back to pin 8, and found that when I sent characters to the UNO via the hardware USB port, they showed up again 'echoed' to the serial output after having traversed the AltSoftSerial port 8/9.
So at this point I have solved the UNO 'half' of the problem; the rest is up to you! ;-)

or maybe they wired the SoftwareSerial to pins 6 and 7 on the shield and not to RX and TX

Or a thousand other possibilities.  I'm not familiar with the SIM shield, so hard for me to say....

then why did you write an answer?

Thanks for you answer, I did come across the software serial not being fully supported however I'm quite a newbie to arduinos. I've moved towards using a different shield for my project but I will try again using your very helpful answer.

Glad to help, and I hope you continue to enjoy your adventures in Arduino-land.  If you have the time, please mark my answer as 'Accepted', as (I think) that will improve my 'reputation' score and let me help others as well.


text:
Communication between arduino nano and MCP3424 over I2c
I'm am completing a project of mine that uses an MCP3424 i2c 18bit ADC and an arduino nano to measure temperature with an NTC thermistor but am having trouble with the arduino wire library. This is my first project using i2c so I'm not very knowledgeable about the subject but I have rigorously read the datasheet of the MCP3424 that can be found at (http://ww1.microchip.com/downloads/en/devicedoc/22088b.pdf)
and tried many different ways to get it working. Also I'm new to posting on this stackexchange so pardon me if my syntax and what not is not right(I'm doing my best). Here is the code I have so far that is on my arduino.
#include<Wire.h>

#define ReadMode 0xDD //Device will output conversion data (7 bits, device address. 1 bit, Read/Write mode)
#define WriteMode 0xDC //Device expects config byte (7 bits, device address. 1 bit, Read/Write mode)
#define ConfigByte18 0x8c //PGA = 1, SPS = 3.75, One-Shot mode, channel 1, initiate new conversion.
#define ConfigByte16 0x88 //PGA = 1, SPS = 15, One-Shot mode, channel 1, initiate new conversion.

void setup() {
  Serial.begin(9600);//Initiate Connection to computer
  Wire.begin();//Initiate Wire library
  Wire.setClock(100000);//make sure clock speed is standard mode
  delay(500);//Allow boot up and settle of ADC
  Wire.beginTransmission(WriteMode);//begin transmission with ADC in Write mode
  Wire.write(ConfigByte18);//configure the ADC with settings found in "ConfigByte18"
  Wire.endTransmission();
  Serial.print("Everything worked\n");

}

void loop() {
  unsigned char x, y, z, a, b, c;
  //Serial.println("Bytes ready to be read:");
  Wire.begin();
  Wire.setClock(100000);//make sure clock speed is standard mode
  Wire.beginTransmission(ReadMode);//begin transmission with ADC in write mode
  Wire.requestFrom(0x6E, 6);//request 6 Bytes of information from MCP3424
  x = Wire.read();//read bytes
  delay(10);
  y = Wire.read();
  delay(10);
  z = Wire.read();
  delay(10);
  a = Wire.read();
  delay(10);
  b = Wire.read();
  delay(10);
  c = Wire.read();
  Serial.print(x);//print bytes
  Serial.print(", ");
  Serial.print(y);
  Serial.print(", ");
  Serial.print(z);
  Serial.print(", ");
  Serial.print(a, HEX);
  Serial.print(", ");
  Serial.print(b, HEX);
  Serial.print(", ");
  Serial.println(c, HEX);
  Wire.endTransmission();
  delay(1000);

}

So an explanation of my understanding: In the “void setup” section I begin transmission in write mode (see page 21 of datasheet to follow along with my explanation figure and table 5-3) in the begin transmission function I address the slave with 0xDC because the device address begins with 1101 (pre programmed) and then 110 as I have the two Adr pins tied to +5v and finally 0 as I want to change configuration settings. This translates to 0xDC in hexadecimal. Then I send the slave a byte of information for the configuration register (see page 18 section 5.2). I send 0x8C as I want my settings to be PGA = 1, SPS = 3.75, One-Shot mode, channel 1, initiate new conversion. Which should mean I need to send the slave 10001100 or 0x8c. This communication then ends as “Any byte sent after this second byte will be ignored” according to page 21. Then in the loop I begin transmission the same way apart from now I open transmission in read mode which is 0xDD as the last bit (R/W bit) is now 1. I then request six bytes of information and read the six bytes. If you now go to page 23 of the datasheet you can follow along again. Here I should get three data bytes from the slave and every subsequent byte should be the configuration register settings repeated. For now I am uninterested in the first three data bytes as I first of all just want to know how to change the configuration settings. What gets printed by the arduino instead is three data bytes from the slave, as expected, and then three of the exact same value, also as expected as they should all be the configuration settings. What is being printed in the second three bytes is “90”. Not what I expected. Now I’ve tried to figure out what has happened (hard without an oscilloscope). 90 converted from hex to binary is 10010000 and I believe the default settings are (which can be found on page 18) 00001001 could this be the default settings if so can anyone tell me whats going on and how to fix it? Thank you in advance for the help and thank you for taking the time to read my problem.

do not initialize the library in every loop. remove begin and setClock. and requestFrom should not be wrapped in transaction

@Juraj okay I will try without initialising the library ever loop and removing the set clock but I don't understand what you mean with the requestFrom being wrapped in transaction, could you explain a little more?

sorry transaction = beginTransmmition
endTransmmition

@Juraj I have tried what you said but still I get the same result

use a library. for example https://github.com/bersch/MCP3424

The problem is, that you misunderstood, how the Wire library handles addresses.
I2C uses an address byte, where the first 7 bits are the actual address and the last bit (Read/Write bit) dictates the direction of the communication. The Wire library gives you different functions for both directions (in your case: Wire.beginTransmission() for master write and Wire.requestFrom() for master read) and hides away the complexity of the Read/Write bit. So what you have to give as an address is the pure address of the device without the Read/Write bit. To write the configuration you used the address 0xDC, but the actual address of the device is 0x6E as you used it in the Wire.requestFrom() call.
Also in your loop() you try to start a master write with Wire.beginTransmission(), though you are starting a master read directly after it. Wire.beginTransmission() and Wire.endTransmission() are purely for master write transactions. So you should delete these lines here. For master read the call to Wire.requestFrom() and the corresponding reading is enough.
What happens in your code: In setup() you write the new configuration data to a wrong address (0xDC instead of 0x6E). The transmission fails, as there is most likely no device with this address at the bus, but you don't notice, since you are not checking the return value of Wire.endTransmission(), which would show an error code. Then in the loop() function you reinitialize and reconfigure the whole Wire library again, which makes no sense, as Juraj mentioned in his comments. Though it will only cost some cycles of computation time. Then the library get's set to master write mode (no actual I2C action here, just interal to the library) and then to master read mode (actual I2C action. The provided number of bytes get's read here from the slave). At the end you say to the library, that is should finish the master write transmission from before, which is not there anymore (since you've done a master read). So this will do nothing. Also you are doing many delays between the reads, which is not necessary. When the Wire.requestFrom() function returns, all the I2C communication is finished. The bytes, that could be received, are received and written into the libraries buffer. Wire.read() will only read the next value from the buffer, remove it from there and return the value. No I2C action at that point, so the delay(10) is useless
TL;DR:

Always use the correct address without Read/Write bit: 0x6E
Initialize and configure the Wire library only once in setup()
Remove Wire.beginTransmission() and Wire.endTransmission() from the loop() function, as you are only doing master read there.
Remove the delay(10); lines between the calls to Wire.read()

Thank you for the answer chrisl this clears up a lot! One more question if i may, to initiate a read from the MCP3424 I need to update a bit in the configuration register. Does that mean every time I want a reading I need to execute the three wire functions beginTransmission(0x6E), Wire.write() and endTransmission?

Yes, when in One Shot mode you need to always do beginTransmission(), write(), endTransmission(), requestFrom() and read() for every measurement. But as you currently are reading contineously from the ADC, you should consider to use the contineous measurement mode, so that the measurement is automatically started at a fixed interval and you only have to request the data from the ADC.

Okay I see how I could do that yes, but in the future I plan on reading from all 4 channels so I would have to change the config byte everytime and use all 5 commands every change anyway right?

Yes, when you change the channels on each request, you must use all the above commands to first set the correct config byte, start the conversion and then actually request the data.


text:
Is AREF a stable output Ref voltage with analogReference(INTERNAL)
I'm using an analog input on a NANO board to measure the midpoint between two photo resistive (Cadmium) cells, with the two outside ends tied to GND and a source voltage. Basically a simple voltage divider. So it almost wouldn't matter what reference voltage I used in a case like that, as long as the AnalogReference() was correctly set corresponding to the reference voltage, AND the load did not pull down that voltage.
Well if I used the 5V for my source, and set AnalogReference(DEFAULT), then assuming a worst case load of 4K-ohm, the total load on the 5V regulator is still only 1.25mA. But even so, I figured I could minimize the system load even more by setting AnalogReference(INTERNAL), and using the VREF pin as a source for my voltage divider.
Well it seems to work fine, but I don't know that I've seen any actual examples of what I'm doing, which is using the AREF pin as a source output voltage for my voltage divider. Using vREF as a source, a 4K load would only draw 27.5 microamps with a 1.1V source. But I can't find any spec for the max current I should avoid exceeding, That has me worried maybe I'm not even supposed to be doing that!
So is it acceptable to use the VREF pin as an output for light loads, when using the INTERNAL AnalogReference?
Thoughts?
EDIT: After receiving a "no" answer yesterday, I did some bench checking. I configured my NANO board for Internal, and connected a fully open 100K linear pot from AREF to Ground, with a DVM in parallel. The AREF terminal output was about 1.076, with or without the 100K load. Not quite the 1.1 specified but close enough. I then slowly rotated the pot to increase load. At just under 9K the voltage dropped a somewhat insignificant amount, to 1.075. From there on there were additional small decreases, down to about 1K, at which point i measured about 1.062V. Below 1K, there was a very steep decrease.
Note that this was a "quickie" test, done while powering the NANO from a USB port. However, repeating the test with 12V on the DV input did not alter the results significantly.
Even considering the USB source, from this test I conclude:
1) There does appear to be some buffering on the VREF output. It certainly did not behave as there was a simple case of a 1.1V source in series with a high impedance.
2) Up to a load of 10K, the VREF output seems at least as stable as the 5.0V regulator output.
3) Since a 1.062 drop from an initial no-load voltage of 1.076 equates to less than a 2% difference, I have to conclude that a load on VREF (to ground) greater than 1K (lets say 2K for margin) makes VREF probably useful in cases like i described, with a worst case load of 4K.
4) I repeated my test with a second NANO board. This time the initial no-load voltage was salightly higher, 1.084. However, the response to increasing load and the K point where the slope changed dramatically were unchanged.
Again, this is an arduino NANO board, and probably a clone. Can anyone else verify or disprove my results? I'm sure someone else will need to consider using VREF as I did, and it would be good to know.

No, it is not acceptable.
The datasheet states:

AVCC is connected to the ADC through a passive switch. The internal 1.1V reference is generated from the internal bandgap reference (VBG) through an internal amplifier. In either case, the external AREF pin is directly connected to the ADC, and the reference voltage can be made more immune to noise by connecting a capacitor between the AREF pin and ground. VREF can also be measured at the AREF pin with a high impedance voltmeter. Note that VREF is a high impedance source, and only a capacitive load should be connected in a system.

The 1.1V reference is only presented on the AREF pin for the purpose of adding an external bypass capacitor, or for measuring it using a very high impedance meter. Any load applied to the pin will cause the reference voltage to droop.
While it may work in certain circumstances it's certainly not recommended. If you want to use it externally you should buffer it through a high-impedance unity-gain voltage follower:

simulate this circuit – Schematic created using CircuitLab

Hmm! OK that's good information! I've been doing it wrong, though it "worked", I suppose it only did so because for a voltage divider it did not matter as much as it otherwise might have! I'll have to re-think my circuit a little bit though. Since I just need an ADC count representative of the voltage divider, it looks like I'd do better to simply use the DEFAULT and work with the 5V terminal for my reference!

Please see my edit. At least based on my bench test, it seems that using the AREF pin to power a low load voltage divider works, within the constraints I documented

It may work, but it's not what it's designed for. My car works when I drive it off a cliff. It's not designed for that though, and I doubt the long-term outcome would be good.  If you want to use it externally you should buffer it through a high impedance unity-gain voltage follower.

I note that you quoted the spec as saying AREF should only be measured with a high impedance voltmeter. But did YOU add the phrase "Note that VREF is a high impedance source, and only a capacitive load should be connected in a system."?
Your car analogy is  poor one. I've been doing what I came for confirmation on for a few years now with no trouble, and it was the lack of examples that made me second guess. I guarantee if you drive your car off a cliff and measure the results, they won't lead you to the reasonable question I raised.

Also I'll point out that a unity gain buffer done with a TL081 (not exactly a "rail-to rail" spec OPAMP) will also start to droop beyond a 1k load. But based on my bench test, I'd not be surprised if I found there already was such a buffer internal to the ATmega328. I don't have the internals, but based on my measurements, there must be some kind of buffer there already.

The tl081 is just what the schematic editor dumps in by default. Select suitable components for your application. Everything I stated is direct from the datasheet. If you think it is wrong then take it up with microchip.

Good point! I will write to them and include my findings!

Now, having had the benefit of a support ticket and subsequent discussion with an engineer at TI on this subject, I can confidently offer a qualified YES to my own question. It turns out my case is probably the only one that would be within those qualifications.

In the case where the RATIO between two hi-resistances is the ONLY thing needed from an A/D measurement, it is acceptable to use AREF and GND for the applied voltage, provided the load is low (see item 2). The main reason is that any droop in the AREF caused by the added load would not affect the ratio.
The use of AREF for such a situation should still ensure limiting any load on the AREF pin to about 91uA. For the 1.1V (INTERNAL) source selection, that equates to about a 12K load. The number is based on a reverse calculation that would cause a 1 LSB difference in analog readings, IF other analog inputs are expected to be used for other non ratio-metric measurements.
Using the AREF pin this way makes it even more important to add a capacitor from the pin to GND.
Apparently there is no danger of harming the chip in any way, should the AREF pin become shorted.

I will comment that the engineer responding to my support ticket understood I was trying to avoid a PCB change, but recommended a different approach if I had occasion to make other board changes anyway. His recommendation was to use the EXTERNAL Analog reference option, using the available 3.3V pin for AREF voltage, and using a digital output to supply my voltage divider. The idea here is that I would still have the benefit of short circuit protection, and since I was concerned about power saving, I could switch the Digital output pin to a low state until readings needed to be taken, observing sensible delay for settling time.
A good suggestion indeed, but my reason for answering my own question here is because under the constraints given, using AREF as described in my OP is acceptable, will not affect the ratio measurement, and could not harm the chip.


text:
Sampling rate of multiple analog pins on Arduino
as I checked on Arduino website, they mentioned all boards: UNO, Nano, Mini, Mega have maximum sample rate 10kHz for each analog pin. So my concern is:
1) is there any difference between sampling rate when reading a single analog pin and multiple analog pins? For example, if we read only 1 analog input, maximum sample rate can reach 10kHz. How about maximum sample rate when we want to read 6 analog inputs? Maximum sample rate will be 10kHz or (10/6)kHz? Can we do analog input reading simultaneously or not?
2) What if I want to get sampling rate at least 1kHz for each Arduino board (assume 5 analog inputs)?
3) In case we need to connect several Arduino boards via I2C or SPI protocol, is sampling rate related to these 2 protocols?

1)  You only have one ADC on board and all the pins run through a mux.  You can only read one pin at time.  If you're willing to give up some resolution then you might can read a little faster but it gets tough.  What's worse is that when you are switching pins really fast it can mess with your readings so that for some things, especially when input impedance is high, you have to read twice and throw away the first reading.  So that essentially cuts your sampling rate in half right there.
2)  That may be doable.  Or at least something close to it.  You'd run in free-running mode and write a tight ISR to read the interrupt when the analog read is finished and record every other value and switch the pin every other time.  Theoretically you should get pretty close to 1kHz with 5 pins.  Maybe a little faster if you give up a little resolution.
3)  Those communications protocols run at light speed compared to the analog read.

What if I need to get sample rate 5kHz for each analog input? Only use 1 analog pin in each Arduino board? Is there any better way?

Get an ADC chip.  They make some really fast ones.  That would make more sense than buying a bunch of Arduino's.

Thanks. By the ways, is there any correlation between baud rate & sample rate? Can you share me a sample code how to do the sample rate settings?

Baud rate is how many bits per second a serial connection sends out.  Sample rate is how many samples per second of a measurement you take.  Thye are two completely different concepts.

I'm sure professor google can find examples of how to run the ADC on the Arduino in free running mode.

Can you suggest me an external ADC chip for 30 analog inputs at sample rate 100Hz? I guess Arduino Mega and 1 ADC chip is ok. Because if we use 2 Arduino Mega connected via I2C, the code maybe more complicated.

I don't know any off hand.  I usually just go to Mouser.com and search there.  They've got a nice search filter feature.


text:
Power supply affecting sensor readings ESP8266 and JSN-SR04T-2.0
I have an ESP8266 Wemos D1R2 Board with a JSN-SR04T-2.0 ultrasonic range finder and everything works perfectly when I have the device connected to my computer USB or via a 12V battery into the onboard regulator via the external power jack. However when I use a 240V AC to 12V DC transformer to power the setup my readings become quite erratic. I have checked the voltage coming out of the power supply (12.48v) and the voltage going to the sensor (3.28V,  I have it coming off the 3.3V pin) and it is the same on each type of power supply so the onboard regulator is working. Can anyone advise what might cause this? The transformer provides 1A which is more than enough as I have measured the peak usage at <100ma

In what sense are your readings "erratic"?  You need to explain.

In the working config I get consistent values for the distance that when converted from the echo time match the tape measure I have between the sensor and the test object. In the erratic version the measurements vary considerably, e.g. for an object 150cm an erratic sample would be 107, 58, 86, 107, 36cm

So the power supply is a switching supply and my sensor is housed in a small aluminium case as it needs to live outdoors and I found that if I connected the case to earth on the same circuit the readings are consistent and correct, I assume this may be something to do with RF from the switching supply don't understand why and could have that totally wrong

The JSN-SR04T-2.0 ultrasonic range finder is rated to 5Volts. giving it 3.3 volts may not be enough. from my limited knowledge it should work if you give it a separate power supply and not depend on the 3.3 volts of the ESP.

According to the datasheet here: https://www.jahankitshop.com/getattach.aspx?id=4635&Type=Product it is rated 3-5V. Note that once I pulled the device out of the aluminium case it has been working fine


text:
If an Arduino goes to sleep, does the attached ESP also sleep?
I am using Arduino Uno + an attached ESP-01 (ESP8266).
I want to save battery, so I made my Arduino get sleep & interrupt by a watchdog timer.
But if the Arduino goes to sleep, does the attached ESP also sleep?

you have to put the ESP8266 to sleep


text:
How to get interrupt while in sleep mode?
I am using Arduino-uno, attached ESP-01 module
I want to give interrupt when I send some wifi-signal to arduino,
which is in sleep mode.
so I write this code:
SoftwareSerial esp(2, 3); // RX, TX

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

  esp.begin(9600);

  attachInterrupt(digitalPinToInterrupt(2),work,RISING);

  delay(1000);

  init_sleep(); // go to sleep
}

void work(){
    light = ! light;

    digitalWrite(12,light);

}

when I don't write down the init_sleep, this interrupt is able to work.
but when the arduino is in sleep mode, because of writing 'init_sleep'
It does not react signal by interrupt.
Is it impossible to wake up sleeping arduino by attachInterrupt() ?
please give me some solution.

Why the delay()? If the interrupt happens while in delay(), it won't wake up the Arduino that is not sleeping yet.

oh I had some mistake. but I deleted the delay, result is same.

Where does init_sleep() come from? I did my a little differently by directly accessing registers but I know you have to disable sleep mode in your "wake up" ISR as the first thing before anything will happen. Watch this tutorial, it is very good. https://www.youtube.com/watch?v=urLSDi7SD8M


text:
Distinguishing between multiple Infra Red Transmitters
I am working on an Arduino project where I use an infra red camera along with 4 transmitters placed each on a corner of a square platform to park a robot perfectly on this platform.
However, it is important for the camera to distinguish between the 4 transmitters.
(it should know the right transmitters from the left and the upper transmitters from the lower).
Can anyone please help me find a solution to this problem?

Why not using a less symmetric shape for the IR transmitters instead of a square. For example an arrow. If you can distinguish between front and back you also can distinguish left and right based on that (assuming, that your robot does not flip between up/down.

Hint: Web-search how the Nintendo controller works.

How do you control where the camera is pointing?  I think I would do something like have the 4 transmitters pulsing at different frequencies, and then have 4 receivers that each look for their matching frequency and ignore others.  Don't you need 6 pairs, for left/right, forward/backward, and up/down?

It's a symmetry problem, you can solve it breaking the simmetry.
Options:

use three transmitter instead of four, the plane and its center is
still determined.
move one transmitter in the middle of the side of the square.
use different duty cycle for one (or more) transmitter.
use linear polarizing filters on the transmitters and a rotating filter on the camera lense.
...

I guess that also SVD could be helpful to find the pattern's center, when the camera is not centered and perpendicular.


text:
NFC wont send URL to mobile phone
I'm using  nfc 2 click (NT3H2111), I tried via arduino to send data to my mobile phone using this code :
#include <Wire.h>

int i = 0;
int j = 0;

uint8_t NDEF_DATA[] = { 0x03, // NDEF Message
15, // Message size
0xD1, // Record header
1, // Type Length - 1 byte
11, // Payload Length - 11 bytes
'U', // Type / URI
0x01, // Payload
'm', 'i', 'k', 'r', 'o', 'e', '.', 'c', 'o', 'm',
0xFE
}; // NDEF Message End Mark

void setup()
{

delay(5000);
Wire.begin();
// initialisation de la liaison I2C
Serial.begin(9600);
// initialisation de la liaison série vers la console

Wipe_Tag() ;

Wire.beginTransmission(0x55);
Wire.write(0x00);
Wire.endTransmission();
Wire.requestFrom(0x55, 7);
Serial.println("UUID:");
while(Wire.available())
{
Serial.print(Wire.read(),HEX);
}

delay(1000);
Serial.println();

Serial.println("Start wrting");
Wire.beginTransmission(0x55);
Wire.write(0x01);

for (i = 0; i < 16; i++)
{
Wire.write(NDEF_DATA[i]); //Fill Block with Data
}
Wire.endTransmission();
delay(50);

Wire.beginTransmission(0x55);
Wire.write(0x02);

for (i = 16; i < 32; i++)
{
Wire.write(NDEF_DATA[i]); //Fill Block with Data
}
Wire.endTransmission();
delay(50);

Serial.println("Start wrting");

}
void loop()
{

}

void Wipe_Tag()
{
for (i = 1; i < 50; i++)
{
Wire.beginTransmission(0x55);
Wire.write(i);
for (j = 0; j < 16; j++)
{
Wire.write(0x00); //Fill Block with Zeros
}
Wire.endTransmission();
delay(50); //Delay 50 ms

}
}

All I get is the right UUID than nothing happened, if I try to put my phone I can't read nothing ( it should send me to mikroe website).
As I'm using the nfc 2 click from mikroe.
Thanks for reading.

I don't know, wild shot in the dark, but which of the fields count towards the message size parameter, but you might want to check it has the right value.
Also do you need a null at the end of the text?

Also, in the loops you are sending 16 bytes, but the NEF_DATA contains 18 bytes.

Hi there, thank you for your help, in fact each register has 16 bits, this is why I divided the data into two registers


text:
My stepper motor connected to a driver and an Arduino is not working
I'm using a 28BYJ-48 stepper motor with a ULN2003 driver board. I'm trying to control the motor using an Arduino MEGA. I initially connected the pins on the driver: IN1,2,3,4 to pins of the Arduino: 8,9,10,11 respectively; as was given in a youtube video I referred to(https://www.youtube.com/watch?v=HdqCtAJxhrs). The power for the motor was given from the 5V and GND ports in the Arduino. What happens is that it rotates 180 degrees,and then stops and then goes at random angles and stops. This was the code:

#include <Stepper.h>

Stepper stepper1(64,8,9,10,11);
int a=1;

void setup() {
  stepper1.setSpeed(50);
}

void loop() {
  while(a<10){
    stepper1.step(2048);
    delay(1000);
    a++;
  }
}

Does anything happen? Have you tried any of the stepper example programs, and do they work? How is your stepper connected? A diagram would be helpful. Is the power supply sufficient for this motor? Can you confirm the supply is working? There is a lot more you could provide in your question - or check for yourself and and provide that information - to help us help you.

@JRobert so it's supposed to keep rotating at 180 degrees with breaks right, but it just rotates once and stops. I was wondering if the power supply would be a problem because right now it's connected to the Arduino. I'll get a power source tomorrow and try again. IN1,2,3,4 were connected to pins 9,11,10,6.

@JRobert, I checked out another video and changed the pin configuration. Other details are updated in the question. If you need any other information then just let me know :)

Most motors need more current than an Arduino pin can supply, so if the stepper driver doesn't power your motors through a separate supply, there is a good chance that is your problem. Arduino pin drivers are supposed to be limited to 20ma nominal, and 40ma absolute max. Trying to draw more than that will likely fail (the device will be under-powered), may damage the pin drivers (by over-heating), and may pull down the Arduino's own supply voltage enough to it to reset (typically cycling itself through startup/attempt to run/reset, ... etc. until you shut it off or something fails).

Hey @JRobert!!! I finally got it working!! So what I did was connected the motor to a 5V 0.3A supply. And then I changed the number of steps per revolution to 2038 and used the code on Michael Schoeffler's website (https://www.mschoeffler.de/2017/09/23/tutorial-how-to-drive-the-28byj-48-stepper-motor-with-a-uln2003a-driver-board-and-an-arduino-uno/). And it finally works!!
Thanks for all the help :)

Glad to hear it - thanks for letting us know.

For those who missed the comments, what I made a mistake in, as @JRobert pointed is that I was suppose to have connected the stepper motor to a separate power supply as the Arduino was not capable of so much resources. I also altered the code as I think I had gotten the steps-per-revolution wrong which is needed in the Stepper function in the Arduino Code. One needs to check this with the datasheet or somewhere online for the respective stepper motor model. The final code that got it working is here. All thanks to @JRobert for helping me figure out the solution :)


text:
I can't write or read data in an external eeprom
I've been trying to store data in an external I2C EEPROM but it doesn't seem to work, and i don't know why.
When i run the i2c scanner it founds my memory but i can't write in it, or at least it seems like i can´t
Please help me :(
(I'm using a 24C512 btw)
#include <SoftwareSerial.h>
SoftwareSerial BT1(3, 4); // RX | TX
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Max72xxPanel.h>
#include <EEPROM.h>

#define EEPROM_I2C_ADDRESS 0x50

//Vcc - Vcc
//Gnd - Gnd
//Din - Mosi (Pin 11)
//Cs  - SS (Pin 10)
//Clk - Sck (Pin 13)

String inicio="";
const int pinCS = 10;
const int numberOfHorizontalDisplays = 8;
const int numberOfVerticalDisplays = 1;
String bt;
//String cadena[]={"holamundooooooooo"};  //textos
int i=0;
Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);

const int wait = 25; // Velocidad a la que realiza el scroll(Velocidad a la que se muestra la frase)

const int spacer = 1;
const int width = 5 + spacer; // Ancho de la fuente a 5 pixeles

void setup()
   {
       Serial.begin(9600);
       Serial.println("Enter AT commands:");
       BT1.begin(9600);

        matrix.setIntensity(15); // Ajustar el brillo entre 0 y 15

 // Ajustar segun las necesidades
 matrix.setPosition(0, 0, 0); // El primer display esta en <0, 0>
 matrix.setPosition(1, 1, 0); // El segundo display esta en <1, 0>
 matrix.setPosition(2, 2, 0); // El tercer display esta en <2, 0>
 matrix.setPosition(3, 3, 0); // El cuarto display esta en <3, 0>
 matrix.setPosition(4, 4, 0); // El quinto display esta en <4, 0>
 matrix.setPosition(5, 5, 0); // El sexto display esta en <5, 0>
 matrix.setPosition(6, 6, 0); // El séptimo display esta en <6, 0>
 matrix.setPosition(7, 7, 0); // El octavo display esta en <7, 0>
 matrix.setPosition(8, 8, 0); // El noveno display esta en <8, 0>

 matrix.setRotation(0, 1);    // Posición del display
 matrix.setRotation(1, 1);    // Posición del display
 matrix.setRotation(2, 1);    // Posición del display
 matrix.setRotation(3, 1);    // Posición del display
 matrix.setRotation(4, 1);    // Posición del display
 matrix.setRotation(5, 1);    // Posición del display
 matrix.setRotation(6, 1);    // Posición del display
 matrix.setRotation(7, 1);    // Posición del display
 matrix.setRotation(8, 1);    // Posición del display

 char bt[]={"prueba"} ;
   }

void loop()
   {
 //bluetooth recoger datos
 if(BT1.available()){
  bt="";
 }
 int i=0;
  while(BT1.available()){
       // Serial.write(BT1.read());
        char c=(char)BT1.read();
        if((c=='a')||(c=='b')||(c=='c')||(c=='d')||(c=='e')||(c=='f')||(c=='g')||(c=='h')||(c=='i')||(c=='j')||(c=='k')||(c=='l')||(c=='m')||(c=='n')||(c=='ñ')
        ||(c=='o')||(c=='p')||(c=='q')||(c=='r')||(c=='s')||(c=='t')||(c=='u')||(c=='v')||(c=='w')||(c=='x')||(c=='y')||(c=='z')||
          (c=='A')||(c=='B')||(c=='C')||(c=='D')||(c=='E')||(c=='F')||(c=='G')||(c=='H')||(c=='I')||(c=='J')||(c=='K')||(c=='L')||(c=='M')||(c=='N')||(c=='Ñ')
        ||(c=='O')||(c=='P')||(c=='Q')||(c=='R')||(c=='S')||(c=='T')||(c=='U')||(c=='V')||(c=='W')||(c=='X')||(c=='Y')||(c=='Z')||(c==' ')){
          bt=bt+char(c);

          writeByte(EEPROM_I2C_ADDRESS,i, (byte)c);

          i++;
          delay(50);

        }else{
          bt=bt;
        }
  }
  Serial.println(bt);

String palabrasacada;
for(int i=0; i<bt.length(); i++){
  byte z=readByte(EEPROM_I2C_ADDRESS,i);
  char a=char(z);
  palabrasacada=palabrasacada+String(a);
}

String cadena[]={palabrasacada};
int n = random(0,1);

 for (int i = 0; i < width * cadena[n].length() + matrix.width() - 1 - spacer; i++) {

 matrix.fillScreen(LOW);

 int letter = i / width;
 int x = (matrix.width() - 1) - i % width;
 int y = (matrix.height() - 8) / 2; // Centrar el texto

 while (x + width - spacer >= 0 && letter >= 0) {
 if (letter < cadena[n].length()) {
 matrix.drawChar(x, y, cadena[n][letter], HIGH, LOW, 1);
 }

 letter--;
 x -= width;
 }
 matrix.write(); // Muestra loscaracteres
 delay(wait);
 }
}

void writeByte(int device, unsigned int add, byte data)
{
  Wire.beginTransmission(device);
  Wire.write((int)(add >> 8)); // left-part of pointer address
  Wire.write((int)(add & 0xFF)); // and the right
  Wire.write(data);
  Wire.endTransmission();
  delay(5);//small delay for eeprom to save data
}

// reads a byte of data to the I2C address 'device', in memory location 'add'
byte readByte(int device, unsigned int add)
{
  Wire.beginTransmission(device); // I2C address
  Wire.write((int)(add >> 8)); // bit shift for high byte of pointer address
  Wire.write((int)(add & 0xFF)); // mask for the low byte
  Wire.endTransmission();
  Wire.requestFrom(device, 1);
  return Wire.read();
}

The led matrix and bluetooth receiving actually works, but i'm adding them anyways, just in case

I don't know the answer, but you can change the big if statement:  if((c=='a')||(c=='b')||(c=='c')||(c=='d')||(c=='e')||(c=='f')||(c=='g')||(c=='h')||(c=='i')||(c=='j')||(c=='k')||(c=='l')||(c=='m')||(c=='n')||(c=='ñ')  ||(c=='o')||(c=='p')||(c=='q')||(c=='r')||(c=='s')||(c=='t')||(c=='u')||(c=='v')||(c=='w')||(c=='x')||(c=='y')||(c=='z') .... == ' '))

by something like if (((c >= 'a') && (c <= 'z')) || (c=='ñ') || ((c >= 'A') && (c <= 'Z')) || (c=='Ñ') || (c == ' '))

@MichelKeijzers You overlooked 'ñ' which actually isn't an ASCII character anyway...

@Majenko I fixed it before reading your comment but you are absolutely right

You're right, thank you

Have you debugged your code to find the problem? For example you can  check the return value of endTransmission() for an error code, that would indicate a problem with I2C transmission

reduce your code to write a single byte, read it back and turn on an LED if the two match ... you can do it in setup() ... no code needed in loop()


text:
Mains And Battery Monitor Using Delay on And Delay off
I am very new to Arduino. In fact I am entirely new to embedded system. I have been using other platforms for my experiments specifically PICs.
I just moved to Arduino for more easier coding but I am hooked somewhere.
Here is the constraints:
In the code I will post below;

When MAINS is present and is within usable range, both MAINS_OK & ENABLE Pins will go HIGH after 3sec delay(non-blocking).
When MAINS is BAD, MAINS_OK Pin will go LOW immediately while ENABLE Pin will wait for 3sec before going LOW.
If MAINS is recovered and is within usable range again, the sequence described in "1." must be followed an so on.

I have tried in so many ways, it is not working as expected. Only the blinking of the SYSTEM LED is working fine.
// constants won't change. Used here to
// set pin numbers:
const int enablePin     = 7;      // the number of the Function Pins
const int lvdPin        = 6;
const int sysledPin    = 5;
const int mainsokPin   = 4;

// Variables will change:
int mainsPin = A0;
int batteryPin = A2;
int MAINS;
int BATT;
int ENABLE = LOW;
int LVD = LOW;
int SYS_LED = LOW;
int MAINS_OK = LOW; // State used to set the Function Pins

long previousMillis1 = 0;
long previousMillis2 = 0;// will store last time PIN was updated
long previousMillis3 = 0;
long previousMillis4 = 0;
long previousMillis5 = 0;

long ENABLE_ON        = 3000;
long ENABLE_OFF       = 3000;
long LVD_ON           = 3000;
long LVD_OFF          = 3000;
long MAINS_DELAY_ON   = 3000;
long MAINS_DELAY_OFF  = 0;
long SYS_LED_ON       = 1000;
long SYS_LED_OFF      = 1000; //Duration of the delay time (milliseconds)

void setup()
{
  pinMode(ENABLE, OUTPUT);  // set the digital pin as output:
  pinMode(LVD, OUTPUT);     // set the digital pin as output:
  pinMode(SYS_LED, OUTPUT); // set the digital pin as output:
  pinMode(MAINS_OK, OUTPUT); // set the digital pin as output:
  pinMode(A0, INPUT); //set pin as Analog nput
  pinMode(A1, INPUT); //set pin as Analog nput
}
void loop()
{
  unsigned long currentMillis1 = millis();
  unsigned long currentMillis2 = millis();
  unsigned long currentMillis3 = millis();
  unsigned long currentMillis4 = millis();

  if ((SYS_LED == LOW) && (currentMillis1 - previousMillis1 >= SYS_LED_OFF))
  {
    SYS_LED = HIGH;  // Turn it off
    previousMillis1 = currentMillis1;  // Remember the time
    digitalWrite(sysledPin, SYS_LED);  // Update the actual SYS_LED
  }
  if ((SYS_LED == HIGH) && (currentMillis1 - previousMillis1 >= SYS_LED_ON))
  {
    SYS_LED = LOW;  // turn it on
    previousMillis1 = currentMillis1;   // Remember the time
    digitalWrite(sysledPin, SYS_LED);    // Update the actual SYS_LED
  }

  MAINS = analogRead(mainsPin);

  //========================= MAINS OK =======================================
  /* If MAINS supply is ok, the MAINS_OK and ENABLE Pins will wait for 3sec
      before going high. Both Pins will go high at the same time.
  */

  if (MAINS >= 84 && MAINS <= 177) // >=0.410V && <=0.864V >=140V && <=250V
    if ((MAINS_OK == LOW) && (currentMillis2 - previousMillis2 >= MAINS_DELAY_ON))
    {
      MAINS_OK = HIGH;  // Turn MAINS_OK on with 3sec delay
      previousMillis2 = currentMillis2;  // Remember the time
      digitalWrite(mainsokPin, MAINS_OK);  // Update the actual MAINS_OK
    }
  if (MAINS >= 84 && MAINS <= 177) // >=0.410V && <=0.864V >=140V && <=250V
    if ((ENABLE == LOW) && (currentMillis3 - previousMillis3 >= ENABLE_ON))
    {
      ENABLE = HIGH;    //Turn ENABLE ON with 3sec delay
      previousMillis3 = currentMillis3;  // Remember the time
      digitalWrite(enablePin, ENABLE);  // Update the actual MAINS_OK
    }

  //=================== MAINS NOT PRESENT or IT IS LOW/HIGH VOLTAGE ====================
  /* As soon as MAINS is lost, whether it enters low voltage or high voltage,
     the PINs MAINS_OK will go LOW imedatly without delay while ENABLE will wait for
     3sec before going LOW. Then If MAINS is restored OK, the initial delay sequence
     must be followed.
  */
  if (MAINS <= 53 || MAINS >= 258) // <= 0.260V || >=1.26V// Below <= 120V and >= 276V
    if ((MAINS_OK == HIGH) && (currentMillis2 - previousMillis2 >= MAINS_DELAY_OFF))
    {
      MAINS_OK = LOW;  // Turn MAINS_OK off after 0sec delay
      previousMillis2 = currentMillis2;  // Remember the time
      digitalWrite(mainsokPin, MAINS_OK);  // Update the actual MAINS_OK
    }
  if (MAINS <= 53 || MAINS >= 258) // <= 0.260V || >=1.26V// Below <= 120V and >= 276V
    if ((ENABLE == HIGH) && (currentMillis3 - previousMillis3 >= ENABLE_OFF))
    {
      ENABLE = LOW;    //Turn ENABLE off aftar 3sec delay
      previousMillis3 = currentMillis3;  // Remember the time
      digitalWrite(enablePin, ENABLE);  // Update the actual ENABLE
    }

  BATT = analogRead(batteryPin);

  //============================ BATTERYERY SETTINGS ==============================
  /* If Battery is below 21V LVD Pin go HIGH with 3sec delay
      When it goes high, it remains high the Batter goes up to 27.6V
      LVD will then go LOW ahter 3sec delay
  */
  if (BATT <= 391) //(1.91V) 21V         // BATTERY Low
    if ((LVD == LOW) && (currentMillis4 - previousMillis4 >= LVD_ON))
    {
      LVD = HIGH; //Turn LVD on with 3sec delay
      previousMillis4 = currentMillis4;  // Remember the time
      digitalWrite(lvdPin, LVD);  // Update the actual LVD
    }

  if (BATT >= 512) // (2.50V)  27.6V         // BATTERY low Recovery
    if ((LVD == HIGH) && (currentMillis4 - previousMillis4 >= LVD_OFF))
    {
      LVD = LOW; // turn LVD off after 3sec delay
      previousMillis4 = currentMillis4;  // Remember the time
      digitalWrite(lvdPin, LVD);  // Update the actual LVD
    }
}

Please What can I add or remove from this code for it to work properly?
Thanks.

When MAINS is OK ... i think that you would get undesired behavior with that test because it is true every time you check the value .... you probably want When MAINS becomes OK  ... that happens only once at transitions between OK and NOT-OK

When MAINS is OK means when mains is within usable range but "MAINS_OK" is a digital output pin.

you are misunderstanding my comment ... if you test for MAINS is OK then you will set the 3 second timer over and over ... you have to test for the transition between NOT-OK and OK

There are lots of problems with your code. To start, most/all of this code is wrong:
  pinMode(ENABLE, OUTPUT);  // set the digital pin as output:
  pinMode(LVD, OUTPUT);     // set the digital pin as output:
  pinMode(SYS_LED, OUTPUT); // set the digital pin as output:
  pinMode(MAINS_OK, OUTPUT); // set the digital pin as output:
  pinMode(A0, INPUT); //set pin as Analog nput
  pinMode(A1, INPUT); //set pin as Analog nput

Those lines should be setting various pins to their desired input/output state. However, you are using the variables you declared to hold their bool status, not their pin numbers.
The variables you are using are declared like this:
int ENABLE = LOW;
int LVD = LOW;
int SYS_LED = LOW;
int MAINS_OK = LOW; // State used to set the Function Pins

Those are not pin numbers, those are variables that hold boolean values.
This line, for example:
pinMode(MAINS_OK, OUTPUT); // set the digital pin as output:

Should almost certainly read
pinMode(mainsokPin, OUTPUT); // set the digital pin as output:

Instead.
Same goes for enablePin, lvdPin, and sysledPin
The two lines
pinMode(A0, INPUT); //set pin as Analog nput
pinMode(A1, INPUT); //set pin as Analog nput

Should probably read
pinMode(mainsPin, INPUT); //set pin as Analog nput
pinMode(batteryPin, INPUT); //set pin as Analog nput

Since you define the variables mainsPin and batteryPin.

Thanks Duncan! I will go now and edit the code according to you advise.


text:
Which Arduino microcontrollers are able to drive a parallel 8-bit ILI9341 display at 320x240@60fps with DMA or extra CPU core or both and how?
I've always wanted to make my own game console. I don't know why the existing Arduino game consoles have this issue with framerate when a 2006's Sony handheld PC had 1GB of RAM and an Intel CPU running Windows XP. Why haven't normal DIY open-sourcing copyright-libertarian hobbyists been able to make something at that magnitude? Don't say money because money is the reason I'm in gamedev scene; wanting to make a game console or anything that has a screen, characters, multimedia and nerdiness to make money.
So the issue has always been how do I find a microcontroller that's enough fast to run a 320x240 display like ILI9341 at 60FPS without stuttering or having to do lots of precalculations for partial screen updates. What about the NES/SNES consoles which didn't even have a framebuffer but which used discrete logic?

My scheme was to use ATXMEGA128A1U with a parallel bus and DMA, but it was hard to find a board containing all the stuff I needed and the External Bus Interface.
Then I tried to use ESP32 with SPI, but SPI would go max to 80MHz while the screen could only handle 40MHz.
Then I tried ESP32 again with 8-bit IO pin permutation which didn't work; it was too slow; maybe it would be faster if I used Xtensa assembly to take advantage of the CPU pipeline in case the dumb C++ compiler compiled machine code that waited 7 cycles for every next operation.
But now I'd like to use ESP32 with an I2S bus and DMA which was used for a camera demo and it was really really fast, but I'd like to use it for I2S output for that ILI9341 display. According to my calculations, it should take 10MHz to write out all of the bytes if the bus is 16-bit wide (8 bits for data and 1 bit for Data/Command register) + Read/Write/Select strobes controlled by the bus interface. However, Bitluni has been able to drive it to out of spec values of 580MHz for his VGA library that's superfast, but that month he had nothing to pay his rent with so he licensed the code under a copyleft license (ShareAlike). You know what they say, "The love of money and the lack of money are the roots of all evil.". Money is important, but really... this just makes money an even worse enemy than it was before.

So I guess I'm out of options. There have been many attempts and they have failed. Yes, there's Teensy and stuff, but I need something in the EU which I won't have to pay for more in shipping than the actual product.
So, what are the solutions?
P.S. if I get one of those "off-topic" or "too-broad" or dislikes to my question, I'm deleting it and moving to Reddit and screenshooting how yet again StackExchange is just too formalistic and banhammersome to open conversations.

While it's not a perfect solution for games, maybe this would interest you...

your post reads like a rant ... it appears that you may be trying to use equipment that is unsuitable for the task ... have you explored something like a Raspberry Pi?

Oh, and the root of evil is not money. The root of evil is -1.

Wow, especially the PS carried some deep anger. That really doesn't animate to give an answer :/

didn't NES have a hardware video controller? ... i think that one of the early game consoles had a 1-video-line buffer

@Majenko, an imaginary root

@jsotola So evil is imaginary?

@Majenko, i was trying to be funny, and failed ... lol ... technically, the root of all evil are people

@jsotola Funny... so was I... :/

Raspberry Pi is ShareAlike/GPL as far as I've been given the impression.

The problem is the whole concept of running an ILI9341 TFT screen at 60FPS from a microcontroller. You can't. It's just not fast enough.
To get those kind of speeds you need to directly interface the TFT panel with the microcontroller. And that takes a special microcontroller with a TFT interface built in.  As well as that you need the memory to store the image that you are displaying on the screen.
There are microcontrollers available that can do it quite happily.  But they aren't in the "maker scene". Simply because they aren't a common thing to do.
For many years now there has been the PIC24 "DA" range of microcontrollers with a built in GPU and TFT interface - but there is no free C++ compiler, so no Arduino support - so no easy route to using them for beginners.
There are now, though, the PIC32MZ "DA" rage which are more accessible - though still very hard to use.  These are much more viable for the kind of thing you want, with 32MB of built in DDR, a TFT panel interface, and available in a 144 pin TQFP chip that is possible for an experienced maker to hand solder.
But the barrier is still software.  While chipKIT has full support for the PIC32MZ "EF" range of chips the "DA" range is not yet supported.  That's not to say you can't work with them, just not with the Arduino API and IDE.
The more common way to make a games console like device is to take an ARM SoC and interface it with a TFT panel directly. The simplest way for a maker to do that is to put a TFT on a Pi and install Retropie.
And we're not against open discussion as people. It's the site. It's not a site for open discussion. It's a question and answer site. You ask a technical question that you need assistance with, and we tell you the answer. It's not a forum for general discussion.  As such, this question will be closed as either "top broad" or "primarily opinion based". However your question does deserve an answer anyway.

Thank you for the comprehensive reply and for considering my question.
Now, I've been working in AVR ASM and in Notepad++ alongside a MSYS32 for ESP32 development for Windows. So, if it's not Arduino, it's not a problem for me. All I need to know is how to access registers and the datasheet that proves the behavior of registers.
An ARM SoC would be good, but I don't want to be bothered with licenses and GPL and ShareAlike and EULAs and patents. Raspberry Pi along with Retropie are not permissive-licensed but copyleft. What ARM SoCs would be good then? Preferably a MIPS SoC?

MIPS is not ARM. Completely different architecture.  The problem with SoCs, especially ARM ones (which are prevalent these days) is the difficulty in getting into them. Not only are they hard to work with (generally high density BGA packages which means specialist production facilities that can handle micro-vias) but most SoC manufacturers want you to jump through hoops before they will even let you see a chip. Broadcom still won't let Raspberry develop proper GPU drivers for their chips because it would end up open source.

Allwinner are better in their openness, but still they are hard to work with.  A meaty MCU (200MHz or faster) with the right interfacing would be easier to get into, but the problem with them tends to be lack of memory. That's where a SoC excels - with the memory external (and DDR is another whole nightmare to develop for) you really aren't limited to what the manufacturer has decided to allow you to have.  When it comes to microcontrollers it really doesn't matter what architecture you go for. Personally I prefer MIPS (PIC32) because I was brought up on MIPS systems at

university (DEC Stations). The new boy on the block, though, Risc V, which is completely open, looks promising. There's some microcontrollers starting to appear. Risc V is based on MIPS, and is available as an open source core for FPGA development. So you could even roll your own system in an FPGA if you want to get really hardcore. That would give you the most flexible system - but again very expensive to get started with. Development tools are $$$$. Plus it takes a whole other set of skills to work with.

I know MIPS is not ARM. The comment length limitation didn't let me say fully. Anyways, I found a European seller of the Teensy 3.5. 3.6 is out of stock (as always). For some weird reason, I cannot find Teensy 3.5 LCD benchmark videos anymore. Google seems to be disranking all non-mainstream things to suck an extreme extent. I'd like to know more about Teensy 3.5 since it's the most powerful thing that's accessible with a decent shipping time/cost, but I need to know the availability of permissive licensed libraries and if 3.5 can do the superfast 3.6's 60fps rendering. I'm unable to get 3.6.


text:
Is DS18B20 temperature sensor makes Arduino processing slow?
I recently run into a problem that causing my whole code processing slow down, for example i had a millis timer set for one minute but it took 1:30m to finish, pressing buttons was laggy etc.
After hours of digging and commenting out codes piece by piece i finally found out what is causing the slow down!
my DS18B20 temperature sensor DATA pin is connected to pin A0 when i remove the library and related codes to the sensor processing became MUCH faster more snappier/responsive...
After googling a bit i realized that everyone connected the sensor to pin 2 of Arduino!
So is the processing slow because DS18B20 is on pin A0 instead of pin 2 or there's something wrong with the sensor itself or it is because of This library?

Indirectly it's the library.
That library uses the OneWire.h library.  The OneWire protocol requires some reasonably precise timing, and because of the the OneWire.h library turns off interrupts while it communicates.
While interrupts are disabled nothing else can happen. That means that the timer interrupt that drives millis() can't "tick" - so the millis count doesn't increase while you communicate with the temperature sensor.

Hi Majenko, which library do you suggest?

There's not really anything you can do on an Arduino. You just have to put up with it and maybe compensate for the time taken communicating.

you mean changing the library not gonna fix the problem?

You would need to do it in hardware. Maybe with a DS2482-100 I2C to OneWire adapter.

this library is not using the onewire.h library. there's no other way?

Yes it is.  In the header file: #include <OneWire.h>

The software function managing the 1-wire protocol generally has several non-interruptable sections in order to ensure the bus timings.  This can make your processor unavailable for long periods of time.
Worse, some implementations do not allow any interrupt at all.
And even if your implemenation would allow being interrupted, it is generally blocking the main loop as it is not executed in an interrupt itself.
Using a hardware implementation for the 1-wire control instead of a full software would release the CPU from managing the timing and waiting for the 1-wire to complete.  But such hardware implementation are not commonly available in microcontrollers.
There is however a middle way.  An open source implementation using the microprocessor's or controller's UART to ensure the timings is available ( https://github.com/MaJerle/onewire_uart ) - MAXIM also has an application note for it ( https://www.maximintegrated.com/en/app-notes/index.mvp/id/214 ).
This also offloads the processor and it can be interrupt driven.
Is the processing slow because DS18B20 is on pin A0 instead of pin 2 ?
That might have an influence if the processor that is on your Arduino board would have a (partially) 1-wire compatible source on another pin, in which case the libary would have to take advantage of that.
Is there something wrong with the sensor itself?
That would not be generally the case, but in case you have two sensors on the same bus, the 1-wire protocol is slower as it needs to find all peripherals and the master has to indicate which one it is addressing.
Is it because of "This library"?
It is not because of that library, but there are other implementations (see the link above) that use hardware resources to improve performance at the cost of using a hardware resource (some MCU's have only 1 HW UART so you'ld not have a second one if you also need RS232 communication for instance on other signal lines).

the UART thing seems pretty awsome but too advanced for a user like me, i tried to read the documents but the more i read more i lost! we connect one side of UART to two transistor and other side goes to arduino? i'll pick your answer as correct one if you please help me figure this out...

The 1-wire bus is bidirectionnal, so it must be possible for the slave to pull the line low.  Standard TX operation of a UART is to always drive the output.  The application note (https://majerle.eu/documentation/ow/html/page_appnote.html ) proposes a solution where two cascaded transistors transform the TX in an open-drain output.  The same application note indicates that if your uC allows opendrain on the output itself, that you do not need this (it is said that the STM32 allows this) - in that case the TX and RX pins are connected together.  In both cases you have a true one-wire bus.


text:
Do we have an alternative for millis() function?
This is actually a follow up question to this question, so basically I'm using DS18B20 temperature sensor which requires Onewire.h library that interrupts millis() function.
Luckily i have a DS3231 RTC module which I'm using it with RTClib library, is there any way to use that module as a timer instead of millis() function?

You can use the SQW output of the module to indicate the passage of precisely 1 second. Every time it transitions from LOW to HIGH one second will have passed.
RTCs cannot give you times of higher resolution than 1 second, but they can give you that 1 second granularity to a high accuracy.

Thanks, but i don't know how to do that! can you please provide a link to an article/tutorial?

digitalRead(). When it changes from LOW to HIGH you know a second has gone by.


text:
How to control 220V RGB Led Strip with Arduino/ESP32
I need to control 220V RGB Led strip with Arduino/ESP32-wroom over internet.
Single color led is easy (just with a relay), 12V RGB can be done with PWM and maybe external power source. But how can I control 220V RGB via MCU?
I couldn't find any answer yet.

there is no such thing as 220 V AC LED (yet). it is a 12 V LED and an AC/DC power supply. what controls does it have?

In Australia, we have LED light bulbs that screw into the 240V light socket. Sure there is circuitry in the bulb to convert the incoming power to suitable ranges for the LED's to operate, but the light bulb is LED based and does require 240V AC. I'm surprised these are not available elsewhere. https://www.beaconlighting.com.au/lighting/globes-bulbs-lights/led-globes-lights

@GMc, yes the LED bulb has AC/DC adapter insight. a dimmable version senses the AC voltage and dims the DC side with PWM. a not dimmable version would not dim with triac. and a RGB version needs some additional controls, usually wireless

Try looking at a relay or a triac.
Also, you can not simply "use PWM to control a 12V circuit from your MCU" which is most likely running at 5V. You need to use a component such as a MOSFET. The MCU controls the MOSFET via the Gate. The MOSFET switches the 12 V circuit off or on based upon the signal at the gate.
Alternatively, like the AC solution, you can use a Relay to control the 12V circuit.

@alper, WARNING! DANGER! this accepted answer is wrong and can destroy your equipment and harm you! Controlling a switching power supply of the AC/DC adapter for the LED strip will destroy the triac and/or the AC/DC adapter.

@juraj, can you elaborate?  From https://www.electronics-tutorials.ws/power/triac.html (and other similar sites) "This makes the triac ideal to control a lamp or AC motor load with a very basic triac switching circuit". Here is a shield designed to do it  https://www.circuitar.com/nanoshields/modules/triac/. And yes, I absolutely agree the voltages the OP is asking about are dangerous and if there is any uncertainty he/she shouldn't go anywhere near it.

@Alper, there are some excellent safety warnings on the site https://www.circuitar.com/nanoshields/modules/triac/ Juraj is 100% correct about the dangers of playing with mains voltages. I encourage you in the strongest possible terms to read the safety information

a switching power supply turns the AC line on and off fast. capacitor does the smoothing of the output. triac dimmer turns the AC line on and off fast too. imagine the resulting effect.

https://www.digikey.com/en/articles/techzone/2011/jul/dimming-leds-with-traditional-triac-dimmers

That is good advice, thanks for including it. I wonder if OP wants to dim or just switch off and on. The OP was pretty vague in general, but the "question" has served to generate some useful contributions (IMHO). Although I would still question as to whether my answer is "wrong" as the digikey article explains how Triacs can be correctly used to Dim an LED.


text:
How to adapt this code using a DF Mini Player and interrupts for the ATTiny85?
So I programmed my Arduino Mega 2560 to play certain sound effects from a DF Mini Player that I have. I  took the base code that I modified from online so some fo the names might seem odd. Currently, when uploaded to the Arudino, it works as it should, "buttonPause" and "play()" only play one of the audio files WHILE I am pressing a button. "buttonNext"/"play1()" and "buttonPrevious"/"play2()" activate a sound when a button is tapped (not held down). To allow the sound effect to play in full only while I'm, holding down "buttonPause," I had to use a delay as well as interrupt to stop the playback as soon as I released the button. However, I know aside from changing pin numbers, there are some other alterations I have to make for the interrupt to adapt it to work with the ATTiny85. Any idea how I can get started on making those changes? I have been confused by the sources I have found online.
Full code for using the DF Mini Player with the Arduino Mega
///              MP3 PLAYER PROJECT
/// http://educ8s.tv/arduino-mp3-player/
//////////////////////////////////////////
#include "SoftwareSerial.h"
SoftwareSerial mySerial(10, 11);
# define Start_Byte 0x7E
# define Version_Byte 0xFF
# define Command_Length 0x06
# define End_Byte 0xEF
# define Acknowledge 0x00 //Returns info with command 0x41 [0x01: info, 0x00: no info]
# define ACTIVATED LOW

int buttonNext = 2;
int buttonPause = 3;
int buttonPrevious = 4;
boolean isPlaying = false;
const byte interruptPin = 3;
volatile byte state = LOW;
int buttonState = 0;
int buttonState1= 0;
int buttonState2= 0;
int ledPin = 9;

void setup () {
pinMode(buttonPause, INPUT);
digitalWrite(buttonPause,HIGH);
pinMode(buttonNext, INPUT);
digitalWrite(buttonNext,HIGH);
pinMode(buttonPrevious, INPUT);
digitalWrite(buttonPrevious,HIGH);
mySerial.begin (9600);
attachInterrupt(digitalPinToInterrupt(interruptPin), pause, CHANGE);
pinMode(ledPin, OUTPUT);

}
void loop () {

buttonState = digitalRead(buttonPause);
buttonState1 = digitalRead(buttonNext);
buttonState2 = digitalRead(buttonPrevious);

if (buttonState == LOW)
  {
      play();
      setColor(255, 0, 222); // red
      digitalWrite(ledPin, HIGH);
      delay(1500);

  }

if (buttonState1 == HIGH)
  {

  }

if (buttonState == HIGH)
  {

  }

  if (buttonState1 == LOW)
  {
      play1();

      delay(100);

  }

if (buttonState2 == HIGH)
  {

  }

    if (buttonState2 == LOW)
  {
      play2();

  }

}

void pause()
{
  execute_CMD(0x16,0,0);

      digitalWrite(ledPin, LOW);
}
void play()
{
  execute_CMD(0x03,0,1);
}
void play1()
{
  execute_CMD(0x03,0,2);
}
void play2()
{

  execute_CMD(0x03,0,3);
}

void execute_CMD(byte CMD, byte Par1, byte Par2)
// Excecute the command and parameters
{
// Calculate the checksum (2 bytes)
word checksum = -(Version_Byte + Command_Length + CMD + Acknowledge + Par1 + Par2);
// Build the command line
byte Command_line[10] = { Start_Byte, Version_Byte, Command_Length, CMD, Acknowledge,
Par1, Par2, highByte(checksum), lowByte(checksum), End_Byte};
//Send the command line to the module
for (byte k=0; k<10; k++)
{
mySerial.write( Command_line[k]);
}
}

Board Layout
The amount and placements of the resistors seemed to reduce the amount of noise as much as possible.

why do you need to use an interrupt?

So that when I release "buttonPause" it immediately interrupts the delay (that allows it to play through without moving to the next audio clip) and stops the playblack. I attempted to use millis instead of delay and interrupt to avail.


text:
how to use hx-53 (IR Transmitter Infrared Sensor Module) with ESP32?
ESP32 tx2 (pin17) and rx2 (pin16) uses 3.3v based signals.
HX-53 data connect to tx2, gnd to gnd and vcc to vin(5v).
But as i can understand HX-53 data input should be 5v based.
How can i solve this problem?
HX-53: https://www.amazon.com/Electronic-Infrared-Emission-Transmitter-Arduino/dp/B07PJC7WSQ
Best regards.
GA

Either level shift chip or a voltage divider. Can you provide a link to the HX-53? Havent found it

The HX-53 look like a IR LED and a current limiting resistor on a small PCB.
It also has a LED and a resistor in series for indication when the invisible IR diode is on or off.
So you can change the resistor to a lower value to match the 3,3 volt output from the ESP32.
Resistor values:
221 = 220 ohm   = IR LED
102 = 1000 ohm  = SMD indicator LED

So replace the 220 ohm with something near 75 ohm.
HX-53

In my case HX-53 worked without any changes on Wemos Di mini, but angle/range to trigger was very small. I did as advised @MatsK, solder a 100 ohm resistor in parallel to 221. So now I have 68,75 ohm resist on 221, but angle/range almost did not increase. Can I make more lower the resistance on 221 (to 30-40 ohm) to increase transmit power even more?
Sorry what I write this as an answer, I can't comment.

@Bleach - If you have a new question, please ask it by clicking the https://arduino.stackexchange.com/questions/ask button. Include a link to this answer if it helps provide context.

I happen to have one just like yours. I was trying to use it on my Arduino to send commands to my AC like a remote but as it turns out, the Vcc pin on the HX-53 breakout board appears to be a dummy and doesn’t connect to anything as far as i know. By right there should be a transistor circuit driving that LED. As it is now, not only is there insufficient current from the signal pin to drive that IR LED for signal bursts, but the red SMD LED in series with the resistor is also stealing some of the current away from the IR LED. In the end, I had to buy a BJT, a standalone IR LED, some resistors and design my own transistor circuit to drive it.
On the transistor’s collector side I had a connection to Vcc and the IR LED in series with a resistor. On the base side was a connection to the signal pin and a resistor. The emitter was connected directly to Ground. Values of the resistors you use will depend largely on the Vcc, the LED max forward current, the specs of the transistor you choose and available current from the power supply.
Hope this helps.


text:
Why is Serial.write() slower than memcpy()?
I use Serial.write() to transmit 53 bytes to PC. For the time measurement I use micros() (before and after the write function). There is a delay of 1s after each transmission.
The time of the Serial.write() function is 532 us with 1000000 baud rate, and 360 us with 9600 baud rate.
The Serial.write() function is clearly asynchronous because the transmission of 53 bytes with 9600 baud rate is 53*8/9600*1e6 = 44167 us. (By the way, in the case of 1000000 baud rate, it is not so obvious that the function is asynchronous.)
I use Serial.availableForWrite() before Serial.write() to confirm that there is enough space in the buffer (this returns 63 each time, the buffer size is default 64).
I don't understand these numbers. Using memcpy() to copy the 53 bytes only takes 32 us. Is copying to the serial buffer not the same as the memcpy() function? And why is there a difference in the copy times when the baud rate is different? Serial.write() is even slower with higher baud rates according to the results. Why does Serial.availableForWrite() return 63 while the buffer size is 64 (according to SERIAL_TX_BUFFER_SIZE)?
Update:
Thanks for all of your answers.
I have tried another library for serial communication: https://github.com/greiman/SerialPort
It seems to be faster than the original one.
I use 2 time measurements and a delay in the code, these 3 deltaTimes represents the whole step as follows:
writeTime + memcpyTime + delaymicros = computedTime != realTime
The first 2 times are measured, the delaymicros is the theoretical delay (900 us), I can compute the step time from these. This computed step time is different from realTime (the measured step time, I measure the whole step too). It seems that the additional time can be found in the delay.
SerialPort library:
100 + 30 + 900 = 1030 != 1350
writeReal = 100 + 1350 - 1030 = 430
Arduino Serial:
570 + 30 + 900 = 1500 != 1520
writeReal = 570 + 1520 - 1500 = 590
Then I measured the delaymicros time (which is 900 us in theory), the missing time can be found there. I programmed 900 us delay, but the real delay was around 1200 in the first, and 920 in the second test.
These measurements can prove the existence of the interrupts, because measuring only the write functions doesn't give all of the writing time (especially with the downloaded serial library).
The downloaded library can work faster, but requires bigger tx buffer because of errors (256 works properly instead of 64).
Here is the code: I use a checkSum in the sendig function (which is 570-532 = 38 us). I use Simulink to receive and process the data.

struct sendMsg1 {
  byte errorCheck;//1

  unsigned long dT1;//4
  unsigned long dT2;//4
  unsigned long t;//4
  unsigned long plus[10];//40
};//53

sendMsg1 msg1;
byte copyMsg1[53];

unsigned long time1;
unsigned long time2;
unsigned long time3;
unsigned long time4;

void setup() {
  Serial.begin(1000000);
}

void loop() {
  sensorRead();
  sendMsg1_f();

  //time3 = micros();
  delayMicroseconds(900);
  //time4 = micros();
}

void sensorRead() {
  time3 = micros();

  msg1.t = micros();
  for (unsigned long i = 0; i < 1; i++) {
    memcpy((void*)&(copyMsg1[i*sizeof(sendMsg1)]), (void*)&msg1, sizeof(sendMsg1));
  }

  time4 = micros();
  msg1.dT2 = time4 - time3;
}

void sendMsg1_f() {
  time1 = micros();

  msg1.errorCheck = 0;
  for (int i = 0; i < sizeof(sendMsg1) - 1; i++) {
    msg1.errorCheck += ((byte*)&msg1)[i];
  }
  Serial.write((byte*)&msg1,sizeof(sendMsg1));

  time2 = micros();
  msg1.dT1 = time2 - time1;
}

Can you provide the code, that you used to get these results?

1 byte of buffer is lost because of ring buffer implementation. tail an head of full buffer can't point at the same index, because tail an head are on same index in case of empty buffer

If you take a look into the implementation:
size_t HardwareSerial::write(uint8_t c)
{
  _written = true;
  // If the buffer and the data register is empty, just write the byte
  // to the data register and be done. This shortcut helps
  // significantly improve the effective datarate at high (>
  // 500kbit/s) bitrates, where interrupt overhead becomes a slowdown.
  if (_tx_buffer_head == _tx_buffer_tail && bit_is_set(*_ucsra, UDRE0)) {
    // If TXC is cleared before writing UDR and the previous byte
    // completes before writing to UDR, TXC will be set but a byte
    // is still being transmitted causing flush() to return too soon.
    // So writing UDR must happen first.
    // Writing UDR and clearing TC must be done atomically, otherwise
    // interrupts might delay the TXC clear so the byte written to UDR
    // is transmitted (setting TXC) before clearing TXC. Then TXC will
    // be cleared when no bytes are left, causing flush() to hang
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
      *_udr = c;
#ifdef MPCM0
      *_ucsra = ((*_ucsra) & ((1 << U2X0) | (1 << MPCM0))) | (1 << TXC0);
#else
      *_ucsra = ((*_ucsra) & ((1 << U2X0) | (1 << TXC0)));
#endif
    }
    return 1;
  }
  tx_buffer_index_t i = (_tx_buffer_head + 1) % SERIAL_TX_BUFFER_SIZE;

  // If the output buffer is full, there's nothing for it other than to
  // wait for the interrupt handler to empty it a bit
  while (i == _tx_buffer_tail) {
    if (bit_is_clear(SREG, SREG_I)) {
      // Interrupts are disabled, so we'll have to poll the data
      // register empty flag ourselves. If it is set, pretend an
      // interrupt has happened and call the handler to free up
      // space for us.
      if(bit_is_set(*_ucsra, UDRE0))
    _tx_udr_empty_irq();
    } else {
      // nop, the interrupt handler will free up space for us
    }
  }

  _tx_buffer[_tx_buffer_head] = c;

  // make atomic to prevent execution of ISR between setting the
  // head pointer and setting the interrupt flag resulting in buffer
  // retransmission
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
    _tx_buffer_head = i;
    sbi(*_ucsrb, UDRIE0);
  }

  return 1;
}

It basically answers all the questions.
If the buffer is empty and it's not sending anything, it'll send the character directly so it's synchronous (but sending the character will be much faster than overhead of function callbacks and so)
No, you cannot use memcpy, as it just replaces buffer, but it does nothing else, like actually start the data register ready interrupt nor proper setting of head/tail counters (it's round buffer, so there can be scenario you'll overwrite something outside of buffer)
And write function is called for each character separately (all other specialisation of write are using this one)
Also if the buffer is full, it'll wait until there is a space for another character.

Copying to the serial buffer is not the same as memcpy(), no.
The serial buffer is a circular buffer. Because of that there are lots of calculations involved in working out exactly where in the buffer to place the next character. That takes time.  memcpy() just copies one block of memory directly over another. It makes no checks, and it can't wrap around like a circular buffer.
The reason why higher baud rates seem slower is because each character is taken from the buffer by an interrupt. The higher the baud rate the more often that interrupt is triggered, and so the more time is spent by the CPU in processing that interrupt to send the next character. And equally, the less time is available to the CPU to process the placing of data into to the serial buffer.

The function you were testing is presumably
Serial.write(const uint8_t *buffer, size_t size).
If you search for it in HardwareSerial.h, you will see
    using Print::write; // pull in write(str) and write(buf, size) from Print

and the implementation is in Print.cpp:
/* default implementation: may be overridden */
size_t Print::write(const uint8_t *buffer, size_t size)
{
  size_t n = 0;
  while (size--) {
    if (write(*buffer++)) n++;
    else break;
  }
  return n;
}

This is writing the bytes one by one, and for every byte, the whole code
of HardwareSerial::write(uint8_t c) is being run. This includes the
tests for full or empty buffer, and the arithmetic for updating
_tx_buffer_head.
As stated in the comment above the code, it would have been possible to
override this with a specialized implementation. In principle, you could
copy the linear buffer into the ring buffer using at most two calls to
memcpy(), and updating _tx_buffer_head only once. That would likely
be more efficient than the current implementation, at least for buffer
sizes in the range you are using (close to, but less than the ring
buffer capacity).
Would it be worth it? Maybe for your use case it would. But it could
also make the code more complex and require more flash. And the benefit
is likely to be really small for people who write small buffers. I am
not sure a pull request implementing this sort of optimization may be
accepted. You may try if you feel like so.


text:
How do I properly trigger the ATMega328 reset pin via software so that the bootloader runs and the firmware can be updated via RX/TX pins?
I am programming my Atmega328P chip via a USB to TTL converter (https://www.amazon.com/gp/product/B075N82CDL/ref=ppx_yo_dt_b_asin_title_o01_s00?ie=UTF8&psc=1)
I am able to upload hex files via the command line and the Arduino IDE when I have the RTS pin of the adapter and a capacitor attached to the !RESET pin of the Atmega. (http://www.electronics-lab.com/wp-content/uploads/2018/09/programming-Uno-on-breadboard.png)
I am also able to upload via the command line when I have a push button attached to the !RESET pin and manually pull it low then begin uploading the firmware within a few moments. (https://cdn.instructables.com/F0L/2F6U/J7AQSHD1/F0L2F6UJ7AQSHD1.LARGE.jpg)
My problem is that for my application I will only have the TX/RX/Vcc/GND pins available (no RTS or push button) and need to reset the micro controller so the bootloader runs and listens to be programmed with updated firmware.
So far I have written a batch file that sends a command to restart the Arduino, and then calls avrdude to upload a hex file. I have tried two methods of restarting the micro controller. I have told it to go to memory location zero, and I have attached an IO pin to the reset and dropped it low (although it stays low until reset, so the reset doesn't really work until I manually remove the wire between the IO pin and the !RESET pin)
My sequence is as follows:

Have Arduino running code:

    int recvByte;
    int delayS = 400;
    int resetPin = 9; //bttom right pin of uC

    void setup() {
      // put your setup code here, to run once:
    pinMode(txPin, OUTPUT);
    pinMode(rxPin, INPUT);
    pinMode(resetPin, OUTPUT);
    digitalWrite(resetPin, HIGH);
    Serial.begin(57600);
    Serial.write("Booted/reset");
    Serial.write("This setup was uploaded with batch");
    }

    void(* resetFunc) (void) = 0;

    void loop() {

    if (Serial.available() )
    {    // get incoming byte:
        recvByte = Serial.read();
        if (recvByte==int('r'))
        {
        Serial.write("resetting");
        delay(10); //wait for last message to send
        //digitalWrite(resetPin, LOW); //commented out because this method stays low until wire is removed
        resetFunc();
        Serial.write("should not see if reset properly");
        }

    }

    delay(100);
    }

2.I then run my batch file.
echo Running upload bat, sending reset command then calling avrdude
cd "C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\"
python "path\sendR.py"
.\avrdude.exe -C"C:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf" -v -patmega328p -carduino -PCOM6 -b57600 -D -Uflash:w:"path\Atmega328code.hex":i

The python sendR.py is to send the "r" character, which the Arduino views as the reset command.
import serial
ser = serial.Serial("COM6", baudrate=57600)  # open serial port
bytes = "r".encode()
ser.write(bytes)
ser.close()
print("End python script")

When I send "r" via Tera Term or python the setup code runs again, but I have not been able to upload with the .\avrdude.exe -C"C:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf" -v -patmega328p -carduino -PCOM6 -b57600 -D -Uflash:w:"path\Atmega328code.hex":i command inside the batch file. If I use the pushbutton to do a hardware reset, this command works without issue.
How can I upload new firmware via the RX and TX pins using software to reset the microcontroller and listen for new code as the bootloader runs?
New ideas tried:
Use a uniform baud rate of 57600 in python and atmega serial setup. I chose this value because the Arduino IDE output this baudrate in avrdude.exe -C"C:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf" -v -patmega328p -carduino -PCOM6 -b57600 -D -Uflash:w:"path\Atmega328code.hex":i

wdt_enable(WDTO_15MS);  resets the MCU 15 millis after called. it is a full reset like with reset pin.

You wrote:

void(* resetFunc) (void) = 0;

This seems to me like an approach worth trying, except that the function
address is wrong. At address zero of the flash you have the start of the
user's code. The bootloader, if you do use one, lives at the end of the
flash. The start address of the bootloader depends on its size, and is
configured by setting some fuses on the chip. If you are using the
popular optiboot (the bootloader of the Uno), you have to jump to
exactly 512 bytes before the end of the flash, i.e.:
void (*resetFunc)(void) = 0x7e00;

Oh, wait... the flash is organized as 16-bit words, so you may have to
use the wordwise address instead:
void (*resetFunc)(void) = 0x3f00;

But do note that, unlike a real hardware reset, this approach does not
reset the peripherals to their normal initial state. You may want to do
it before jumping to the bootloader.

Edit: I have disassembled a test program that does this kind of
call-by-pointer, then double checked the documentation of the icall
instruction. It appears that the function address you provide is
indeed interpreted as a word-wise address, so you should write half the
byte-wise address. If you write anything larger than the size of the
flash (0x4000 = 16 kilowords), the most significant bits get
lost, and the address gets reduced to the correct range modulo the flash
size.
That is, if 0x7800 worked for you, then presumably the correct address
is 0x3800, i.e. 2 kilowords (4 KB) before the end of the
flash. This is quite a large bootloader, and the largest size supported
by the ATmega328P. Are you sure it is righ? Aren't you sliding through
some uninitialized flash before hitting the bootloader? Here is a table
that gives the bootloader's start address as a function of the amount of
memory reserved for it:
reserved size  start address
    512 B         0x3f00
     1 KB         0x3e00
     2 KB         0x3c00
     4 KB         0x3800

Note that the Arduino Uno uses optiboot, which fits into the
smallest size that can be allocated to a bootloader (512 bytes).

Thank you! The batch file works with the chip after changing the chip code to void(* resetFunc) (void) = 0x7e00;

The location I had to use was 0x7800; but it is working perfectly for me now. Thank you again!

I think this eats up your memory after a few reboot cycles as you call them as a function which requires some space on stack. Wouldn't be using the wdt the way to go for a proper reboot?

@Kwasmich: The bootloader may reset the stack pointer. If it doesn't, the user's program certainly does: it's one of the first things done by the C runtime. The WDT trick can be useful nevertheless because it resets all the I/O ports to their initial values.


text:
How to change the resolution of DS18B20?
I'm using DS18B20 sensor with this library, the 750ms delay is causing problem in timer part of my code. the code below is from DallasTemperature.cpp:
// returns number of milliseconds to wait till conversion is complete (based on IC datasheet)
int16_t DallasTemperature::millisToWaitForConversion(uint8_t bitResolution) {

    switch (bitResolution) {
    case 9:
        return 94;
    case 10:
        return 188;
    case 11:
        return 375;
    default:
        return 750;
    }

I'm reading the temperature like this:
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS A0
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

void setup() {}

void loop () {
    float currentTemp = sensors.getTempCByIndex(0);
    sensors.requestTemperatures();
}

sensor is not connected in parasite mode, and there is only one sensor.
How can i change the resolution from 12 to 9 bit?

Simple:
sensors.setResolution(9);

It normally defaults to 9, but then probes the connected device to find the maximum resolution it supports and sets it to that. This would normally be done in sensors.begin() which you omitted from your snippet above. If you don't have that it will be on 9 bit anyway, and also the bus probably won't work regardless.

thanks, do i have to declare the address too? sensors.begin(); sensors.setResolution(9); should be in void setup?

sensors.begin() finds the number of sensors connected and works out the maximum resolution supported. sensors.setResolution(9) sets the resolution for all future transactions for all connected devices.

Seems to work better:
sensors.setResolution(tempDeviceAddress, TEMPERATURE_PRECISION);