text:
Help with getting Sensor Average using Arrays
First of all, let me be clear: I'm a total noob, I have close to zero programming experience and I know i'm out of my league, but I want to learn and understand.
Here's the issue. The following code has been made to control heat pads using 4 relays that turn off/on depending on the temperature that 4 lm35 Temp sensors pick up. Because these sensors can be jumpy sometimes, I want to get the average temperature from, let's say, 50 readings, and make the code check THAT data instead of the raw temp reading.
I have the code for the arduino (I wrote some code and guys over other forums took it and modified it to make it shorter (and that kind of lost me, but the code works)
and then I searched smoothing data and got a piece of code that does exactly what I want: make an array, calculate the average temp, and keep deleting and adding new data.
I tried to join both codes together and I got all different kind of errors, lol
So here I am.
The Code that works without average data is this one:
const byte tempPin[] = {A1, A2, A3, A4};
const byte relayPin[] = {6, 7, 8, 9};

// hysteresis = upperLimit - lowerLimit
const byte lowerLimit = 24;
const byte upperLimit = 31;

float tempC[4];
word reading[4];

word printInterval = 1000; // 1 second
unsigned long printCheck = 0, lastPrintTime = 0;

void setup()
{
  analogReference(INTERNAL);
  Serial.begin(115200);
  for (int i = 0; i < 4; i++) {
    pinMode(relayPin[i], INPUT_PULLUP);
    pinMode(relayPin[i], OUTPUT); // defaults HIGH, relay OFF
  }
}

void loop()
{
  // readings and control
  for (int i = 0; i < 4; i++) {
    reading[i] = analogRead(tempPin[i]);
    tempC[i] = reading[i] / 9.31;

    if (tempC[i] < lowerLimit) {
      digitalWrite(relayPin[i], LOW);   //relay OFF
    }
    else if (tempC[i] > upperLimit) {
      digitalWrite(relayPin[i], HIGH);  // relay ON
    }
  }
  printCheck = millis() - lastPrintTime;
  if (printCheck >= printInterval) {
    for (int i = 0; i < 4; i++) {
      Serial.print("tempC");
      Serial.print(i + 1);
      Serial.print(" ");
      Serial.println(tempC[i]);
    }
    Serial.println();
    lastPrintTime = millis(); // reset print timer
  }
}

The average code I got from Arduino Learning center is this one:
/*

  Smoothing

  Reads repeatedly from an analog input, calculating a running average
  and printing it to the computer.  Keeps ten readings in an array and
  continually averages them.

  The circuit:
    * Analog sensor (potentiometer will do) attached to analog input 0

  Created 22 April 2007
  By David A. Mellis  <dam@mellis.org>
  modified 9 Apr 2012
  by Tom Igoe
  http://www.arduino.cc/en/Tutorial/Smoothing

  This example code is in the public domain.

*/

// Define the number of samples to keep track of.  The higher the number,
// the more the readings will be smoothed, but the slower the output will
// respond to the input.  Using a constant rather than a normal variable lets
// use this value to determine the size of the readings array.
const int numReadings = 10;

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average

int inputPin = A0;

void setup() {
  // initialize serial communication with computer:
  Serial.begin(9600);
  // initialize all the readings to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

void loop() {
  // subtract the last reading:
  total = total - readings[readIndex];
  // read from the sensor:
  readings[readIndex] = analogRead(inputPin);
  // add the reading to the total:
  total = total + readings[readIndex];
  // advance to the next position in the array:
  readIndex = readIndex + 1;

  // if we're at the end of the array...
  if (readIndex >= numReadings) {
    // ...wrap around to the beginning:
    readIndex = 0;
  }

  // calculate the average:
  average = total / numReadings;
  // send it to the computer as ASCII digits
  Serial.println(average);
  delay(1);        // delay in between reads for stability
}

The monster I created joining both codes is this one:
const byte tempPin[] = {A1, A2, A3, A4};
const byte relayPin[] = {6, 7, 8, 9};

// hysteresis = upperLimit - lowerLimit
const byte lowerLimit = 24;
const byte upperLimit = 31;

float tempC[4];
word reading[4];

const int numReadings = 50;
int readings[numReadings];
int readIndex = 0;
int total = 0;
float average[4];

word printInterval = 1000; // 1 second
unsigned long printCheck = 0, lastPrintTime = 0;

void setup()
{
  analogReference(INTERNAL);
  Serial.begin(115200);
  for (int i = 0; i < 4; i++) {
    pinMode(relayPin[i], INPUT_PULLUP);
    pinMode(relayPin[i], OUTPUT); // defaults HIGH, relay OFF
  }
  for (int thisReading = 0; thisReading < numReadings; thisReading++){
    readings[thisReading] = 0;
  }
}

void loop()
{
  // readings and control
  for (int i = 0; i < 4; i++) {
    reading[i] = analogRead(tempPin[i]);
    tempC[i] = reading[i] / 9.31;
    total[i] = total[i] - readings[readIndex];
    readings[readIndex] = tempC[i]
    total[i] = total[i] + readings[readIndex]
    readIndex[i] = readIndex[i] + 1 ;
    if (readIntex[i] >= numReadings) {
      readIndex = 0;
    }
    average[i] = total[i] / numReadings;

    if (average[i] < lowerLimit) {
      digitalWrite(relayPin[i], LOW);   //relay OFF
    }
    else if (average[i] > upperLimit) {
      digitalWrite(relayPin[i], HIGH);  // relay ON
    }
  }
  printCheck = millis() - lastPrintTime;
  if (printCheck >= printInterval) {
    for (int i = 0; i < 4; i++) {
      Serial.print("tempC");
      Serial.print(i + 1);
      Serial.print(" ");
      Serial.println(tempC[i]);
    }
    Serial.println();
    lastPrintTime = millis(); // reset print timer
  }
}

These are the errors that I got:
Arduino: 1.6.8 (Windows 7), Board: "Arduino/Genuino Uno"

\temprelayfinal2.ino: In function 'void loop()':

temprelayfinal2:40: error: invalid types 'int[int]' for array subscript

     total[i] = total[i] - readings[readIndex];

            ^

temprelayfinal2:40: error: invalid types 'int[int]' for array subscript

     total[i] = total[i] - readings[readIndex];

                       ^

temprelayfinal2:42: error: expected ';' before 'total'

     total[i] = total[i] + readings[readIndex]

     ^

temprelayfinal2:44: error: 'readIntex' was not declared in this scope

     if (readIntex[i] >= numReadings) {

         ^

temprelayfinal2:47: error: invalid types 'int[int]' for array subscript

     average[i] = total[i] / numReadings;

                         ^

exit status 1
invalid types 'int[int]' for array subscript

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

I typically use something like avgTemp = (9*avgTemp + 1*reading)/10;.

It looks like you might need to handle a two-dimensional readings[4][50] array to keep 50 samples of 4 different measurements.   Gerben's, solution is an "Exponentially Weighted Moving Average" that is an excellent solution with minimum memory and bookkeeping requirements.  You remember only the 4 averages, and adjust them a little bit with each new reading.   For something corresponding to the 50-sample history, you might want a weights like {49/50 ,1/50}

For efficiency reasons, I like to make the time constant a power of two times the sampling period. E.g. avg += (reading - avg) >> 6;, for τ = 64.

Woah, that's excelent thinking although I don't quite understand some things:
Why use Exponentially Weighted Moving Average instead of Simple Moving Average?
And I don't get the code Gerben used. Why multiply the var by 9 and add it to 1*reading?

“Why use Exponentially Weighted Moving Average instead of Simple Moving Average?” Because the former is actually simpler to implement than the latter. It also requires less memory and is faster to compute. “I don't get the code Gerben used.” It's pretty straight forward once you understand the math.

Ok I think I get it. One question though. What gives the weight its value?

I was also wondering what gives the weight its value and I found the answer here: https://youtu.be/NxTFlzBjS-4?t=275 In a nutshell: the .9 weight is comparable to averaging over the past 10 values, if you used .98 instead, you would be averaging approximately over the past 50 values.

total[i] = total[i] - readings[readIndex];

total is of type int. That is, it is a scalar integer. You cannot index into it, total[i] doesn't make sense. That is why the compiler is complaining.

I see. So, how can I make subdivisions of the var total for each sensor/relay set?

You could make total an array (if I understand what you're asking).

Using the exponential moving average filter suggested by Gerben, things
become quite simpler:
const byte tempPin[] = {A1, A2, A3, A4};
const byte relayPin[] = {6, 7, 8, 9};

// hysteresis = upperLimit - lowerLimit
const byte lowerLimit = 24;
const byte upperLimit = 31;

const int numReadings = 64;
const word printInterval = 1000; // 1 second

float tempC[4];
unsigned long lastPrintTime = 0;

void setup()
{
  analogReference(INTERNAL);
  Serial.begin(115200);
  for (int i = 0; i < 4; i++) {
    digitalWrite(relayPin[i], HIGH);
    pinMode(relayPin[i], OUTPUT);
  }
}

void loop()
{
  // readings and control
  for (int i = 0; i < 4; i++) {
    float raw_temp = analogRead(tempPin[i]) / 9.31;
    tempC[i] += (raw_temp - tempC[i]) / numReadings;  // filter
    if (tempC[i] < lowerLimit) {
      digitalWrite(relayPin[i], LOW);   //relay OFF
    }
    else if (tempC[i] > upperLimit) {
      digitalWrite(relayPin[i], HIGH);  // relay ON
    }
  }
  if (millis() - lastPrintTime >= printInterval) {
    for (int i = 0; i < 4; i++) {
      Serial.print("tempC");
      Serial.print(i + 1);
      Serial.print(" ");
      Serial.println(tempC[i]);
    }
    Serial.println();
    lastPrintTime = millis(); // reset print timer
  }
}

I wonder whether this code could be (very slightly) improved by initializing tempC[i] with the first raw_temp reading? Wouldn't this significantly increase the accuracy of the first readings (i.e. tempC[i])? In many use cases, this will not matter practically but in some it might, especially if numReadings and/or printInterval is high. So if you agree, what would be the most elegant way to implement this?

@Christoph: Initializing tempC[i] the way you suggest would indeed improve the first readings, at the cost of slightly increased complexity. The most elegant implementation would probably be a “filter” class that handles the initialization itself when it gets the first reading. The simplest would be to explicitly initialize the array in setup().

Cool! I was wondering exactly that: is it "allowed" to already take a first sensor reading in setup()? So if it is, it sounds like it's the simplest solution (instead of adding a flag-variable or even a class). I realize that "simplest" is not always the same as "most elegant". Thanks!


text:
Help, I want to turn relay constantly on until a difference is detected, but triggered only one instead
Help, I want to use arduino to control relay for electricity, i get data from a sensor and when a value is detected it should be constantly on until another detection triggered again, i can get the program to work but triggered only once instead when it should be constantly turned on, here'e my code:
int Pinout = 13;

void setup() {
    Serial.begin(9600);
    pinMode(Pinout, OUTPUT);
}

void loop() {
    int val = analogRead(A0);
    if (val <= 500) {
        digitalWrite(Pinout, LOW);
    }
    else {
        digitalWrite(Pinout, HIGH);
    }
}

the relay i am using is a chinese relay module with 3 pin and VCC and GND connected to external power supply, and INput pin to 13 digital pin Arduino and the relay is which i believed is Active LOW, and for analog read i am using moisture sensor

you forgot to ask a question .. you also forgot to tell us if you are having some kind of a problem

@jstola: " i can get the program to work but triggered only once instead when it should be constantly turned on" (emphasis mine)

As far as I can see, the relay will stay on when val is less or equal than 500, and stay off when val is higher than 500.
However, there might be a problem when val keeps fastly moving around 500; it will switch on and off quite fast.
To prevent this, you should make two 'triggers', e.g. turn it on when the value <= 480, and turn it off when the value >= 520. When it is in between 480 and 520 it will not change. This will cause less fast changes of the relay. Of course if the initial value is already between 480 and 520 you have to make a choice yourself.

source: Stack Exchange

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

sort: votes


text:
7 segment with arduino
I am getting error with this. It is displaying those segments which are not to be displayed, i.e., 3.141 is dark and other segments are red. And I have checked that the seven segment module I am having is common anode type only.
#include "SevSeg.h"

SevSeg sevseg; //Initiate a seven segment controller object

void setup() {
    byte numDigits = 4;
    byte digitPins[] = {2, 3, 4, 5};
    byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12, 13};
    sevseg.begin(COMMON_ANODE, numDigits, digitPins, segmentPins);
    sevseg.setBrightness(1000);
}

void loop() {
    sevseg.setNumber(3141, 3);
    sevseg.refreshDisplay(); // Must run repeatedly
}

How did you wire the display. Have a schematic?

What dispatch are you using. Seems like it has  active high hardware on the segments

its schematic is on website sunrom.com , as it's device of the same company with model number 1188. although its been out dated, but I need solution..

sunrom.com    model no. 1188

http://www.sunrom.com/p/4x-7-segment-display-multiplexed

sevseg.begin(P_TRANSISTORS, numDigits, digitPins, segmentPins);

using this,, it correctly works,,....... Thankyuiiiii

If you use this library, then use
sevseg.begin(P_TRANSISTORS, numDigits, digitPins, segmentPins);

P_TRANSISTORS because the schematic has PNP transistors?

@linhartr22 probably, but I just went straight to the source code to see with options had active-low for both the digits and the segments.

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


text:
Why NEC IR remote control decoder does not work
I need to recognize a signal from an IR remote, not to use a library for working with IR remotes/receivers. How can when the button is clicked to display its name. I have PIC12F615 microcontroller with this code: code and 5 buttons connected to him and I need recognise which button pressed. Why NEC IR remote control decoder does not work, it doesn't set nec_ok to true.If output nec_state to the terminal, I get 0 1 0 1 0 1 and so on.
    boolean nec_ok = 0;
byte i, nec_state = 0, command, inv_command;
unsigned int address;
unsigned long nec_code;

void setup() {
Serial.begin(9600);
// Timer1 module configuration
TCCR1A = 0;
TCCR1B = 0; // Disable Timer1 module
TCNT1 = 0; // Set Timer1 preload value to 0 (reset)
TIMSK1 = 1; // enable Timer1 overflow interrupt
attachInterrupt(digitalPinToInterrupt(2), remote_read, CHANGE); // Enable external interrupt (INT0)
}

void remote_read() {
unsigned int timer_value;
if(nec_state != 0){
timer_value = TCNT1; // Store Timer1 value
TCNT1 = 0; // Reset Timer1
}
switch(nec_state){
case 0 : // Start receiving IR data (we're at the beginning of 9ms pulse)
TCNT1 = 0; // Reset Timer1
TCCR1B = 2; // Enable Timer1 module with 1/8 prescaler ( 2 ticks every 1 us)
nec_state = 1; // Next state: end of 9ms pulse (start of 4.5ms space)
i = 0;
return;
case 1 : // End of 9ms pulse
if((timer_value > 19000) || (timer_value < 17000)){ // Invalid interval ==> stop decoding and reset
nec_state = 0; // Reset decoding process
TCCR1B = 0; // Disable Timer1 module
}
else
nec_state = 2; // Next state: end of 4.5ms space (start of 562µs pulse)
return;
case 2 : // End of 4.5ms space
if((timer_value > 10000) || (timer_value < 8000)){
nec_state = 0; // Reset decoding process
TCCR1B = 0; // Disable Timer1 module
}
else
nec_state = 3; // Next state: end of 562µs pulse (start of 562µs or 1687µs space)
return;
case 3 : // End of 562µs pulse
if((timer_value > 1400) || (timer_value < 800)){ // Invalid interval ==> stop decoding and reset
TCCR1B = 0; // Disable Timer1 module
nec_state = 0; // Reset decoding process
}
else
nec_state = 4; // Next state: end of 562µs or 1687µs space
return;
case 4 : // End of 562µs or 1687µs space
if((timer_value > 3600) || (timer_value < 800)){ // Time interval invalid ==> stop decoding
TCCR1B = 0; // Disable Timer1 module
nec_state = 0; // Reset decoding process
return;
}
if( timer_value > 2000) // If space width > 1ms (short space)
bitSet(nec_code, (31 - i)); // Write 1 to bit (31 - i)
else // If space width < 1ms (long space)
bitClear(nec_code, (31 - i)); // Write 0 to bit (31 - i)
i++;
if(i > 31){ // If all bits are received
nec_ok = 1; // Decoding process OK
detachInterrupt(0); // Disable external interrupt (INT0)
return;
}
nec_state = 3; // Next state: end of 562µs pulse (start of 562µs or 1687µs space)
}
}

ISR(TIMER1_OVF_vect) { // Timer1 interrupt service routine (ISR)
nec_state = 0; // Reset decoding process
TCCR1B = 0; // Disable Timer1 module
}

void loop() {
Serial.println(nec_ok);
if(nec_ok){ // If the mcu receives NEC message with successful
nec_ok = 0; // Reset decoding process
nec_state = 0;
TCCR1B = 0; // Disable Timer1 module
address = nec_code >> 16;
command = nec_code >> 8;
inv_command = nec_code;

attachInterrupt(digitalPinToInterrupt(2), remote_read, CHANGE); // Enable external interrupt (INT0)
}
}

Schema:

There are some coding issues to clear up before proceeding much further. Variables set in an ISR but used in the loop() should be volatile, e.g. nec_ok. Ensure also that compiler warnings are enabled in the IDE and clean up as required. There are probably other issues.

changed variables to volatile, if a warning is displayed: warning: 'timer_value' may be used uninitialized in this function, note: 'timer_value' was declared here
unsigned int timer_value;

unsigned int timer_value;  make this static as so  static unsigned int timer_value = 0; . As static, it is initialised only once and holds its value between invocations of the calling routine (which is probably what you want here).

nothing changed, the same problem

I think that you have at least one basic problem that timer1 (16 bit) with a prescaler of /8 has a period of ~32ms. A typical NEC data stream is twice that. In the overflow vector of timer1 you reset everything. Anyway, instead of manipulating Timer1, you can simply use micros(). When you enter the routine, calculate the length of the last pulse and preserve the time (in microseconds) you entered the routine for the next entry. Something like pulseLengthLastUs = micros() - enteredAtUs ; enteredAtUs = micros() ;

To find out how far you are getting, create a global error variable, say volatile uint32_t errFlag Set it when there is a value out of range say errFlag = 2000000 + timer_value where the 2000000 represents case 2. Stop the program as soon as there is an error by doing something like this in the loop(): if (errFlag > 0) { Serial.println(errFlag) ; while(true) ; }

I changed to micros but still not working code

It looks much simpler but (a) remember volatile variables volatile boolean nec_ok = 0; (b) adjust the times for us and not the doubled timer ticks (c) add the suggested debug stuff so you know where it first fails.

If output nec_state to the terminal, I get 0 1 0 1 0 1 and so on,  if output pulseLengthUs to the terminal, I get 338020
380
176
200
180
196
176
200
176
200
180
196
180
964
1148
1056
1404
2680
2676
804
1164
1656
528
1552
39964
304
200
176
200
176
200
176
840
2800 for one click

you should have at least 67 time intervals ... read this https://techdocs.altium.com/display/FPGA/NEC%2bInfrared%2bTransmission%2bProtocol ... or this https://www.digikey.ca/en/maker/blogs/2021/understanding-the-basics-of-infrared-communications ... and this https://circuitdigest.com/microcontroller-projects/build-your-own-ir-remote-decoder-using-tsop-and-pic-microcontroller

If use timer I have this time values: 0
122
122
96
96
32
32
33
33
28
28
33
33
32
32
33
33
31
31
1827
1827
1736
1736
133
133
3422
3422
1072
1072
1072
112
112
95
95
32
32
29
29
150
150

you don't have enough time intervals ... the ones that you do have, are not in correct proportions

then what's wrong?

Please show your latest code. Maybe use the same link as before.

code

start by examining the remote control ... is it sending the correct code? ... also, please clean up your code ... it is a mess ... indent it properly and move comments away from the code ... comments are not part of the code

I used an oscilloscope link, yellow pin 5, blue pin 2, and this solution works solution

why are you posting this question again?

here is another question and code

looks like the same question

External interrupt version of NEC protocol decoder using micros() for timing instead of Timer 1.
Drops NEC repeat codes,
Otherwise, in the style of the code in the question.
volatile boolean nec_ok = 0;
byte command, inv_command;
volatile byte nec_state = 0 ;
unsigned int address;
volatile unsigned long nec_code;
volatile uint32_t errFlag = 0 ;
volatile uint32_t decodeStartAtMs = 0 ;

void setup() {
  Serial.begin(9600);
  pinMode( 2, INPUT_PULLUP ) ;
  attachInterrupt(digitalPinToInterrupt(2), remote_read, CHANGE); // Enable external interrupt (INT0)
}

void remote_read() {

  static byte i = 0 ;
  static bool wasSpace;
  static unsigned long enteredAtUs = 0 ;
  static unsigned long pulseLengthLastUs ;

  wasSpace = ! digitalRead( 2 ) ;
  pulseLengthLastUs = micros() - enteredAtUs; // Calculate pulse length
  enteredAtUs = micros(); // Store current time for next entry

  switch (nec_state) {

    case 0 : // Wait here until 9ms pulse found )
      if ( pulseLengthLastUs > 8000 && pulseLengthLastUs < 10000 ) {  // got a 9ms pulse
        decodeStartAtMs = millis() ;  // for timeout
        nec_state = 1 ;
        nec_code = 0 ;
        i = 0 ;
      }
      break;

    case 1 : // handle 4.5ms space
      /*
      if ((pulseLengthLastUs > 2000) && (pulseLengthLastUs < 2500)) {
          // silently drop repeat codes !!!
          nec_state = 0; // Reset decoding process
      }
      else
      */
      if ((pulseLengthLastUs > 5500) || (pulseLengthLastUs < 3500)) {
        errFlag = 10000000 + pulseLengthLastUs ;
        nec_state = 0; // Reset decoding process
      }
      else
        nec_state = 2; // Next state: end of 562µs pulse (start of 562µs or 1687µs space)
      break;

    case 2 : // handle 562µs or 1687µs space
      if ((pulseLengthLastUs > 1900) || (pulseLengthLastUs < 400)) { // Time interval invalid ==> stop decoding
        errFlag = 20000000 + pulseLengthLastUs ;
        nec_state = 0; // Reset decoding process
        break;
      }

      if ( wasSpace ) {
        // we are interested only in the space length
        if ( pulseLengthLastUs > 1000) // If space width > 1ms (short space)
          bitSet(nec_code, (31 - i)); // Write 1 to bit (31 - i)
        else // If space width < 1ms (long space)
          bitClear(nec_code, (31 - i)); // Write 0 to bit (31 - i)
        i++;
        if (i > 31) { // If all bits are received
          i = 0 ;
          nec_ok = 1; // Decoding process OK
          detachInterrupt(0); // Disable external interrupt (INT0)
        }
      }
      break;
  }
}

void loop() {

  if ( errFlag > 0 ) {
    Serial.print( "Error: " ) ;
    Serial.println( errFlag ) ;
    errFlag = 0 ;
  }

  if ( nec_state > 0 && millis() - decodeStartAtMs > 90 ) {
    Serial.println( "Timeout" ) ;
    nec_state = 0 ;
  }

  if (nec_ok) {
    Serial.print( "Code received = " ) ;
    Serial.println( nec_code, HEX ) ;

    address = (nec_code >> 16) & 0xFF; // Extract address from received code
    inv_command = (nec_code >> 8) & 0xFF; // Extract inverted command from received code
    command = nec_code & 0xFF; // Extract command from received code
    if (command == ((~inv_command) & 0xFF)) { // Verify command validity
      Serial.print("Received valid NEC code: ");
      Serial.print(address, HEX); Serial.print(", ");
      Serial.print(command, HEX); Serial.print(", ");
      Serial.println(inv_command, HEX);
    }
    else {
      Serial.println("Received invalid NEC code!");
    }
    nec_ok = 0; // Reset decoding process
    nec_state = 0; // Reset decoding state
    attachInterrupt(digitalPinToInterrupt(2), remote_read, CHANGE); // Re-enable external interrupt (INT0)
  }

}

This utility can be used to verify the output of an IR receiver showing the timings of the pulses and spaces to  4us resolution.
// protocol analyser utility
// intended to dump timings to the serial console for example from demodulated NEC IR codes
// Connect the IR receiver output to pin 2

const uint8_t DATA_SIZE = 100 ;

struct intervalRead_t {
  uint32_t durationUs ;
  bool space ;
} ;

intervalRead_t intervalRead[ DATA_SIZE ] ;

volatile unsigned long enteredAtUs = 0 ;
volatile uint8_t index = 0 ;
volatile bool firstPulse = true ;

void saveTimes() {

  bool wasSpace;
  uint32_t pulseLengthLastUs ;

  wasSpace = ! digitalRead( 2 ) ;
  pulseLengthLastUs = micros() - enteredAtUs; // Calculate pulse length
  enteredAtUs = micros(); // Store current time for next entry

  if ( firstPulse ) {
    firstPulse = false ;
    index = 0 ;
  }
  else {
    if ( index < DATA_SIZE  )  {
      intervalRead[ index ].durationUs = pulseLengthLastUs ;
      intervalRead[ index ].space = wasSpace ;
      index++ ;
    }
  }
}

void setup() {
  Serial.begin(9600);
  pinMode( 2, INPUT_PULLUP ) ;
  attachInterrupt(digitalPinToInterrupt(2), saveTimes, CHANGE); // Enable external interrupt (INT0)
}

void loop() {
  if ( !firstPulse && micros() - enteredAtUs > 500000UL  ) {
    for ( uint8_t i = 0; i < index ; i++ ) {
      Serial.print( i ) ;
      Serial.print( "\tinterval= " ) ;
      Serial.print( intervalRead[ i ].durationUs ) ;
      Serial.print( "us  \t") ;
      Serial.print( intervalRead[ i ].space ? "space" : "pulse" ) ;
      Serial.println( ) ;
    }
    Serial.println( ) ;
    firstPulse = true ;
  }
}

For some reason it does not output anything to the console

nec_state always zero and pulseLengthLastUs 238000
380
176
196
176
196
184
192
184
192
176
196
184
960
1072
1132
376
804
2292
2676
1552
2676
1500
1604
40988
304
196
176
196
176
196
176
836
2800

If using your code, print from console when button pressed:  no code
no code
1C0
1DF
3
E
no code
1

How did you get those figures? You can't put a print() statement in function remote_read() because it is an ISR and will any way mess up the timings especially when printing so slowly at 9600 baud. The PIC software appears to generate an NEC repeat code if the button is held in. The code I supplied ignores these. Try only momentarily pressing the button when testing.

I only momentarily pressing the button when testing, but it doesn't print anything

i changed to your updated code but still not working

You've removed any print statements you added to the ISR? Did you see any message on the console at all? You can try temporarily changing the 31 here to say 30 or 29 just to see if there is a missing end pulse. if (i > 31) { // If all bits are received. If that does nothing, you'll have to work out how to use the proteus logic analyser. The oscilloscope resolution is too poor. I tested that code with an NEC remote control before posting it, but not the changes.

pulseLengthLastUs is always false in this condition: pulseLengthLastUs > 8000 && pulseLengthLastUs < 10000 on any button press

There is then a mismatch between the code https://github.com/circuitvalley/IR-Remote-Control/blob/master/NEC%20IR%20Transmitter%20Remote/main.c (NEC) and its performance on a virtual PIC in that Proteus environment. That the 9ms NEC header could not be found is a strong indication of a timing problem. Use a logic analyser/(oscilloscope) to check the wave form and that the carrier is 38kHz. The carrier frequency is not critical but could be an indication that the PIC or environment is incorrectly configured. Maybe, just for testing, use an Arduino IR library.

The results don't look like proper NEC codes and the program will block the ISR for an extended period which may cause other things to go wrong. Whether that matters is another question. Anyway, I added an additional sketch to the end of the one that I provided in the answer. It will print out the timings of an IR data stream and could be used to see where the timing issues are.

displays the following when I press the button: screen

That is an ~8kHz signal with a 33% duty cycle. It is one quarter of the expected speed. It looks like the speed is too slow for that IR receiver component you are using to demodulate it and is passing it directly through, assuming you measured it at pin 2 of the Arduino. Anyway, without proper use of the tools in that simulator to check the timings, the exercise is like tapping in the dark.

but the frequency on the irlink component is 38kHz

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


text:
How much time does it take to propagate the control signal through all LEDs in the ws2812b strip?
In my next small Arduino project, I wanted to use some addressable rgb led strips.
I made some small research and choose to use a strip with ws2812b.
Generally, I know how this works but I am not 100% sure if what I think is correct. So please correct me if I am wrong.
For each pixel in the strip, we need to send 24 bits to control it.
If we have 10 pixels in a strip then we need to send 240 bits. Then first pixel reads all 240 bits, sets itself color, and lastly propagates other 216 bits to the next pixel. And so on to the last pixel.
I am wondering, how much time does it take to update state of the last pixel in strip?
If sending 24 bit takes something about 30us (1.25us for 1 bit) then is that mean that sending signals to the last pixel in a strip with 10 pixels would take 300us + 270us + 240us + ... + 30us or is it rather just 300us?

it works like a row of buckets ... data fills the first bucket ... when the bucket is full then everything gets passed to the next bucket ... so, after reset, the first 24 bits go to the first LED ... the rest of the bits pass through... same thing happens at the second LED

I have a page about the WS2812 chip along with a suggested way of writing code simply for it. It also describes the timing.
The documented timing for a 0-bit is 1150 ns and for a 1-bit is 1300 ns.

Thus, if we assume all bits are on, then 24 bits would take 24 * 1300 ns which is 31.2 µs.
Since the bits are propagated along the strip, then it would take 10 * 31.2 µs (312 µs) to send all 10 colours.
What I mean by "propagated" is that as each bit arrives at each chip it also forwards it onward to the next chip, much like a shift register. Thus the more bits you send the further the original ones are "pushed" towards the end of the strip.
As the documentation describes, each chip "reshapes" the incoming bit, so that any jitter or noise in the arriving bit is cleaned up as it is forwarded so that the individual bits do not degrade as they are forwarded. Think of Chinese Whispers - because of the reshaping by each chip the information is not corrupted as it is passed on.
Then you send 50 µs of 0V to latch the new colours to the entire strip.
So, the answer to your question is 362 µs (roughly).


text:
ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function
This question comes on the heels of this question
In the last question I learned how to use an initializer list to solve my issue, but working with ros::Subscriber is requiring a different solution.
I'm dealing with a callback in this scenario. If I leave the callback as a standalone function then the program runs but I have no access to class members and methods inside the function which defeats the purpose. Here is my standalone callback:
void setPRYCallback( const std_msgs::Empty& toggle_msg) {}

Once I move this into my class is when I encounter the error.
steps to implementing into class
// add member variable for callback
protected:
  void setPRYCallback( const std_msgs::Empty& );

...

// ass method
void ROSController::setPRYCallback( const std_msgs::Empty& toggle_msg) {}

...

// set initializer list
ROSController::ROSController() : sub("setPRY", &setPRYCallback )

How do I thwart this error while keeping my callback as a class method?
Program with Standalone Function Callback (program runs)
#include <ros.h> // https://github.com/ros-drivers/rosserial/blob/jade-devel/rosserial_arduino/src/ros_lib/ros.h
#include <std_msgs/Empty.h>

class ROSController {
  protected:
    ros::Subscriber<std_msgs::Empty> sub;
    ros::NodeHandle _nh;
  public:
    void loop();
    ROSController();
};

void setPRYCallback( const std_msgs::Empty& toggle_msg) {}

ROSController::ROSController()  {
  this->_nh.initNode();
  this->_nh.subscribe(sub);
}

void ROSController::loop() {
  this->_nh.spinOnce();
  delay(1000);
}

Program with Method Callback (program fails)
#include <ros.h> // https://github.com/ros-drivers/rosserial/blob/jade-devel/rosserial_arduino/src/ros_lib/ros.h
#include <std_msgs/Empty.h>

class ROSController {
  protected:
    ros::Subscriber<std_msgs::Empty> sub;
    ros::NodeHandle _nh;
    void setPRYCallback( const std_msgs::Empty& );
  public:
    void loop();
    ROSController();
};

void ROSController::setPRYCallback( const std_msgs::Empty& toggle_msg) {}

ROSController::ROSController() : sub("setPRY", &setPRYCallback )  {
  this->_nh.initNode();
  this->_nh.subscribe(sub);
}

void ROSController::loop() {
  this->_nh.spinOnce();
  delay(1000);
}

arduino mega

Is there somewhere we can see this "ros.h" library you are using?

This will do the trick: https://github.com/NimbRo/nimbro-op-ros/blob/master/src/nimbro/contrib/roscpp/include/ros/ros.h

Start by making "setPRYCallback" static.

When you move the setPRUCallback function into your class you change the prototype (well, C++ changes the prototype) from:
void setPRYCallback( const std_msgs::Empty& toggle_msg) {}

to:
void setPRYCallback( ROSController *this, const std_msgs::Empty& toggle_msg) {}

That is now not what the callback registering function expects, and so it breaks.
By making the method static it removes that *this parameter, but also means that the function can only access static data within your class (variables also marked static) and there is only one copy of the function (and static variables) shared between all instances of the class (maybe not what you want).

If you define instance as a global value, how about to set callback with using lambda expression as variable of constructor.
#include <ros.h>
#include <std_msgs/Empty.h>

class ROSController {
  protected:
    ros::Subscriber<std_msgs::Empty> sub;
    ros::NodeHandle nh;
  public:
    ROSController(void (*staticPRYCallback)(const std_msgs::Empty& msg));
    void begin();
    void loop();
    void setPRYCallback( const std_msgs::Empty& );
};

void ROSController::setPRYCallback(const std_msgs::Empty& toggle_msg) {}

ROSController::ROSController(void (*staticPRYCallback)(const std_msgs::Empty& msg))
  : sub("setPRY", staticPRYCallback )  {
}

void ROSController::begin() {
  nh.initNode();
  nh.subscribe(sub);
}

void ROSController::loop() {
  nh.spinOnce();
}

ROSController rosController([](const std_msgs::Empty& msg){
  rosController.setPRYCallback(msg);
});

void setup() {
  rosController.begin();
}

void loop() {
  rosController.loop();
  delay(1000);
}

Reference (A post of my blog in Japanese)
https://asukiaaa.blogspot.com/2020/09/define-cpp-callback-for-class-value-with-using-lambda-as-a-variable.html

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


text:
MCP4725 not working
I tried using a MCP4725 DAC with an Arduino (M0 Pro, Duemilanove and Diecimila) and it is not outputing any voltage (just random noise).
I've been using the 2 tutorial codes fount here : https://learn.adafruit.com/mcp4725-12-bit-dac-tutorial/using-with-arduino which are supposed to generate a sinus wave and a triangle wave.
I am pretty sure it doesn't come from the Arduino because basic examples have been working so far.
Anybody had the same issue or can help on this ?
#include <Wire.h>
#include <Adafruit_MCP4725.h>

Adafruit_MCP4725 dac;

void setup(void) {
  Serial.begin(9600);
  Serial.println("Hello!");

// For Adafruit MCP4725A1 the address is 0x62 (default) or 0x63 (ADDR pin tied to VCC)
  // For MCP4725A0 the address is 0x60 or 0x61
  // For MCP4725A2 the address is 0x64 or 0x65
  dac.begin(0x62);

  Serial.println("Generating a triangle wave");
}

void loop(void) {
    uint32_t counter;
    // Run through the full 12-bit scale for a triangle wave
    for (counter = 0; counter < 4095; counter++)
    {
      dac.setVoltage(counter, false);
    }
    for (counter = 4095; counter > 0; counter--)
    {
      dac.setVoltage(counter, false);
    }
}

How do you know its not outputting what you expect?  Have you tried outputting a constant voltage and measuring that?  What does the second parameter do?

I have an electrometer on the output.
Yes.
2nd parameter is a storeflag that indicates to the DAC whether it should store the value in EEPROM so that next time it starts, it'll have that same value output. You shouldn't set the flag to true unless you require it as it will take longer to do, and you could wear out the EEPROM if you write it over 20,000 times.

The output you are generating is a triangle wave, as it states in the program. To see that you need an oscilloscope. I haven't seen an Electrometer since the 18th century.

So if i just do dac.setVoltage(1000,false); I should get a constant voltage on the electrometer right ?

Maybe on a voltmeter you might, yes. Please call it what it is, not what it was known as 200 years ago. Unless you really have got your hands on a modern electrometer, in which case you must have huge amounts of spare cash lying around.

It's written electrometer on it.

I finally got this example to work.
Details:
My A0 line was tied to ground using the solder jumper (through a 10k SMD resistor on the board it appears).
I used . . .
define MCP4725_ADDR 0x62
. . . as the base address of the chip.
My CMD to update the DAC was . . .
Wire.write(64);
. . . (64 in decimal i.e. 0b01000000)
This YouTube video helped out a lot:
https://www.youtube.com/watch?v=ngvqgIeaS9M
All the best
KenLaszlo


text:
Unreliable EspSoftwareSerial Bluetooth transmission for longer read/writes on ESP8266
I have a project which runs on an ESP8266 and one functionality is to do nothing else but to read what comes in from a HC-05 Bluetooth adapter via SoftwareSerial and outputs the read data to the HardwareSerial TX pin. Vice versa, the same is done with what kind of data comes in via HardwareSerial's RX pin and is output to the HC-05 via SoftwareSerial. I use this cheap serial-to-bluetooth adapter, to flash a device where the stock adapter would cost me 100$ or more.
On the surface, the code still runs fine, as most of the time no errors occur. But after some handshake data is transmitted and the flashing begins with larger blocks of data (100+ bytes), the device I'm talking to quits the communication. I can't really figure out why because I don't have access to its internals, but when I flash the ESP8266 with a binary of my software that is about a year old, the communication is much more stable and most of the flash procedures work fine.
I have checked my code and it is basically the same as a year ago, except for the SoftwareSerial constructor and the .begin statement which changed a while ago. But other than that, there is nothing much I can see.
Of course it could be changes inside the EspSoftwareSerial library or even the framework. I was using 2.3.3 until a while ago, but I can't recall which version of EspSoftwareSerial I used a year ago. I tried 2.3.3 for the framework and 5.0.4 for EspSoftwareSerial via configuration in platformio.ini, but to no avail.
Is there anything known about changes in behaviour in EspSoftwareSerial or in relation to the framework that I shoudl consider?
Here's the relevant code:
void handle_bluetooth() {

//  SoftwareSerial BtSerial(2, 0, false, 256);
  SoftwareSerial BtSerial;

  if (!webServer.authenticate(http_user, http_pass)) {
    return webServer.requestAuthentication();
  }

  unsigned long timeout = millis();
  uint16_t idx = 0;
  uint8_t bt_read = 0;
  uint8_t bt_write = 0;
  uint16_t crc_result = 0;
  boolean need_flash = false;
  boolean fw_poll = false;
  boolean fw_memory = false;
  uint8_t model_no = webServer.arg(0).toInt();

  String message = "";
  if (model_no > 0) {
    message.concat(F("Emulating model no. "));
    message.concat((String)model_no);
  }
  webServer.send(200, "text/html", message);

//  BtSerial.begin(38400);
  BtSerial.begin(38400, SWSERIAL_8N1, 2, 0, false, 256);

  telnetClient.println(F("Starting Bluetooth mode..."));
  while (timeout + 300000 > millis()) {

    while (BtSerial.available() > 0) {
      bt_read = BtSerial.read();
      if (bt_read == 0x02 || idx > sizeof(rx_msg)) {
        idx = 0;
      }

      telnetClient.print(to_hex(bt_read));
      telnetClient.print(F(" "));
      rx_msg[idx] = bt_read;
      if (bt_read == 0x03) {
        telnetClient.println();
        crc_result = decodeMsg(idx+1);

        if (rx_msg[3] == 0x27 && model_no > 0) {
          fw_poll = true;
          fw_memory = false;
          telnetClient.println(F("FW request detected."));
        }
        if (rx_msg[3] == 0x25 && rx_msg[4]+rx_msg[5]+rx_msg[7] == 0 && (rx_msg[6] == 4 || rx_msg[6] == 4)) {
          fw_poll = true;
          fw_memory = true;
          telnetClient.println(F("FW memory request detected."));
        }

        if (rx_msg[3] == 0x64) {
          telnetClient.println(F("BT-Address detected:"));
          for (int x=4; x<10; x++) {
            if (CMD[x]!=rx_msg[x]) {
              need_flash = true;
              CMD[x] = rx_msg[x];
            }
            telnetClient.print(to_hex(CMD[x]));
            telnetClient.print(F(" "));
          }
          telnetClient.println();
        }
      }
      Serial.write(bt_read);
      idx++;
      timeout = millis();
      yield();
    }

    while (Serial.available() > 0) {
      BtSerial.write(bt_write);
      if (bt_write == 0x03) {
        telnetClient.println();
      }
      yield();
    }
  }
  telnetClient.println(F("Exiting Bluetooth..."));
  BtSerial.flush();
  BtSerial.end();
  Serial.begin(38400);
  while (Serial.read() >= 0) {    // flush the receive buffer
    yield();
  };
}

uint16_t decodeMsg(uint16_t idx) {
  uint16_t counter = 0;
  uint16_t i = 0;
  while (i < idx) {
    if (rx_msg[i] == 0x1B) {
      rx_msg[counter] = rx_msg[i + 1];
      rx_msg[counter] = rx_msg[counter] - 0x20;
      i++;
    } else {
      rx_msg[counter] = rx_msg[i];
    }
    i++;
    counter++;
  }
  if (crc8(rx_msg, counter - 2, 1) != rx_msg[counter - 2]) {
    telnetClient.print(F("CRC error in message received: "));
    telnetClient.print(to_hex(crc8(rx_msg, counter - 2, 1)));
    telnetClient.print(F("/"));
    telnetClient.print(to_hex(rx_msg[counter - 2]));
    telnetClient.print(F("/"));
    telnetClient.println(to_hex(counter));
    return 0;
  } else {
    return counter;
  }
}


text:
use more no of batteries for more current for servos,why using motor shield?
motor driver is for current amplification.for that we could connect more batteries to servos to get more current.but why are we using motor shields?

Questions on this site must be clearly stated and specific.  Perhaps you should read a bit about the difference between radio control type servos which have their own drive electronics, vs. DC motors that do not and so need external drivers.  Also you cannot simply connect more batteries to most servos - they have voltage limits!

Because science.

Possible duplicate of What is the advantage of using a motor shield if I want to use a stepper motor?

The motor shield is useful because you cannot pass the required amount of current through Arduino's microcontroller without blowing it up.
Of course you don't need to use the motor shield if you create a similar circuit of your own that performs the same task.


text:
Teensy 2.0 MIDI: Number of notes in a chord limited to 6?
I am using the Teensy 2.0 with USBMidi in a project that allows musicians to use retro computers as "instruments" (https://github.com/fredlcore/midijoy). So far, all these computers had no more than four voices, so the problem I am encoutering now has not arisen so far.
When I now want to play a chord with more than six notes simultaneously, only the first six notes are received and played. However, if I release two from, let's say, eight notes, the remaining two notes are subsequently being played if these keys are still kept pressed.
Here is a script reduced to the bare minimum, when you press eight keys on the MIDI device one after another, you'll see that it stops after the sixth key, and when you then subsequently keep all keys pressed and release one after the other, you'll see that the "remaining" keys/notes will be received then:
void setup() {
  Serial.begin(38400);
  usbMIDI.setHandleNoteOn(doNote);
  usbMIDI.setHandleNoteOff(doNoteOff);
}

void loop() {
  usbMIDI.read();
}

void doNote(byte channel, byte pitch, byte velocity) {
  Serial.println(channel);
  Serial.println(pitch);
}

void doNoteOff(byte channel, byte pitch, byte velocity) {
  Serial.println(channel);
  Serial.println(pitch);
}

You have to configure the Teensy as a MIDI device so that the USBMidi libraries will be found.
Is there a hardware limit in the Teensy 2.0 that will prevent it from processing more than six notes at a time? Or is this a constraint within the library?

MIDI has no concept of chords. It's more likely whatever it is you're using to send the MIDI messages that can't cope with more than 6 note polyphony.

Connect the keyboard to a PC and run a MIDI monitor. I guess that you will see the same problem.

@Majenko pointed me to the root cause of the problem: I was sending MIDI notes via Ableton's feature of using the computer's keyboard. It seems that the OS (or the keyboard) cannot send/receive more than six simultaneous keystrokes.

It's OK to accept your own answer as the solution to the problem. You may have to wait for 48 hours before you can accept it.

That's a feature of USB keyboards. They have "N-key rollover" where N=6. I.e., the HID report has space for 6 keys in it.

@Majenko: Yes, that makes sense. Do you want to write up an answer yourself so I can accept it as a solution?

No, yours is good enough. Accept your own when the system lets you.

Ok, will do....


text:
Gyro not zero when returning to original position after random rotations
I am currently trying to make a self balancing robot. Making good progress but stumbled across an issue.
My gyroscope readings do not return to zero if I return in to its original position after random rotations around all 3 axes. Meaning rotation when all angles are not zero.
I am confident this issue is not caused by accuracy of the numerical integration as I have tried jerking the sensor incredibly hard around 1 axis, yet it still returns to 0 when rotated back.
I managed to get the gyro to return to zero when rotating around 1 axes when 1 angle is not zero. Meaning if Y is 45, and I rotate Z 90 degrees, I can transfer the Y angle to X, and once I return all angles back to zero individually, I can return to the original position. I've done this for all 3 pairs of angles (XY, XZ, YZ) and tried to add all 3 equations but the end result does not zero the gyro.
Anyone know any resources that I can look up on, or any idea of what the solution could be? Any help is appreciated.

what happens if your code reads and processes only one of the axes?

You mean to see if that axis returns to 0 after random rotations in all 3 axis? If it's just rotation in that axis, without my attempt to correct 2 axis, it will return to 0. The main issue I need fixed is when the vehicle is vertical, XYZ rotation is set to Z. As the vehicle tries to balance, it will end up rotating a bit as well because I don't have speed encoders yet. When it's tilted along Z and rotates around the vertical axis, the 0 of Z will shift, then the vehicle will try to maintain a forward tilt instead.

Which Arduino board, what sensor, which libraries, what sketch do you use? how is the sensor connected? I would try to jump out of this problem by buying another sensor and using other code. Perhaps even make a leap forward and use a bno055.


text:
Using EEPROM Anything in loop()
I'm trying to make a programm for Arduino Bluno Beetle, that saves a string in the loop. Here is my code:
#include <EEPROM.h>
#include <EEPROMAnything.h>
struct config_t{
   String lastThing;
    } savedValues;
void setup(){
   EEPROM_readAnything(ADDR, savedValues);
   Serial.println(lastThing);
}
String readString="asd";
void loop() {
 //...
 lastThing=readString;
 EEPROM_writeAnything(ADDR, savedValues);
}

(The EEPROMAnything.h can be found here: https://playground.arduino.cc/Code/EEPROMWriteAnything?action=sourceblock&num=1)
The code works until the 11th line. It gives there the following error:
'lastThing' was not declared in this scope

Does anybody know how to fix this problem?

lastThing is neiher a global nor a local variable. It is the name of a member in the config_t structure. What do you want to do in the loop?

My program receives data from a mobile phone with bluetooth, and writes it to an OLED screen. I need the EEPROM to save the last sent thing, and at a reboot to write it on the screen.

EEPROMs have limited writes, if you write to it in a loop you will exhaust all your writes very quickly!

Lol. Putting that write in the loop is a quick way to exhaust your eeprom.

The 'current' version of the EEPROM library (which should be included with the IDE) has EEPROM.put, which is designed to write any variable type. As a bonus, it only writes if the data is different, so can use it repeatedly without wearing out your EEPROM (as much).

See https://www.arduino.cc/en/Tutorial/EEPROMPut

it will not write the content of the String object to EEPROM. the String object handles a pointer to a character array on the heap. but it contains only a pointer.

The proper syntax for referring to a struct member is [structName].[memberName]. Changing lastThing in lines 8 & 13 to savedValues.lastThing fixes the "undeclared" error.

Very huge disclaimer: the code in this answer is untested, and moreover I never played with String objects (I don't like dynamic allocation on arduino). Consequently bugs are expected in this code. If you find any (for instance, the relocation does not work how I suppose, or the parameters should be passed in another way in the read function) please write in the comment so I can fix this
EDIT: Since there were complaints about this, I tested it and.. It works. The read and write functions work so, in the end, it appears that all the researches I did for this answer were complete and allowed me to correctly implement it

As pointed out, lastThing is not a variable, it is a field in the savedValues variable. So the correct syntax would be
lastThing=readString;

This said, your code won't work and has performance issues. First of all it uses the EEPROM.write method, which overwrites the value in eeprom thus lowering its life, and then you will save a pointer to a memory area (4 bytes), which is not the thing you want to save.
In my opinion, it is better to save it "manually":
// Write i in EEPROM, starting from address addr.
// Return the number of bytes written (2 if everything is ok)
uint16_t writeUInt16ToEeprom(uint16_t addr, uint16_t i)
{
    uint16_t currAddr = addr;

    // Only if there is enough space
    if ((currAddr + 2) <= E2END)
    {
        // Write the 2 bytes in eeprom
        EEPROM.update(currAddr++, i >> 8);
        EEPROM.update(currAddr++, i & 0xFF);
    }
    return (currAddr - addr);
}

// Write s in EEPROM, starting from address addr.
// Return the number of bytes written
uint16_t writeStringToEeprom(uint16_t addr, String s)
{
    uint16_t currAddr = addr;

    uint16_t len = s.length();

    // Only if there is enough space
    if ((currAddr + len + 2) <= E2END)
    {
        // Write the string length
        currAddr += writeUInt16ToEeprom(currAddr, len);

        // Write the string bytes
        for (uint16_t i = 0; i < len; i++)
            EEPROM.update(currAddr++, s.charAt(i));
    }

    return (currAddr - addr);
}

// Read i from EEPROM, starting from address addr.
// Return the number of bytes read (2 if everything is ok)
uint16_t readUInt16FromEeprom(uint16_t addr, uint16_t & i)
{
    uint16_t currAddr = addr;

    // Only if there is enough space
    if ((currAddr + 2) <= E2END)
    {
        i = EEPROM.read(currAddr++);
        i = i << 8 | EEPROM.read(currAddr++);
    }
    return (currAddr - addr);
}

// Read s from EEPROM, starting from address addr.
// Return the number of bytes read
// S should be already allocated when entering the function
uint16_t readStringFromEeprom(uint16_t addr, String & s)
{
    uint16_t currAddr = addr;

    uint16_t len = 0;
    s.remove(0);

    // Check if there is enough space for the length
    if ((currAddr + 2) <= E2END)
        currAddr += readUInt16FromEeprom(currAddr, len);

    // Check if there is enough space left for all the chars
    if ((currAddr + len) <= E2END)
    {
        s.reserve(len); // Should allocate only once, thus speeding up

        for (uint16_t i = 0; i < len; i++)
            s.concat((char)(EEPROM.read(currAddr++)));
    }
    else
        currAddr = addr;

    return (currAddr - addr);
}

String lastThing;

void setup(){
    readStringFromEeprom(ADDR, lastThing);
    Serial.println(lastThing);
}

String readString="asd";
void loop() {
    //...
    lastThing=readString;
    writeStringToEeprom(ADDR, lastThing);
}

Note: you should also check the values returned from the functions to check whether the writing or reading was successful.
In this case I did not use the struct, since in your example the struct is not used. If you really need it, because for instance you want to save also an int, you can do something like this:
struct config_t{
    String lastThing;
    uint16_t myIdx;
} savedValues;

uint16_t writeUInt16ToEeprom(uint16_t addr, uint16_t i)
...

uint16_t writeStringToEeprom(uint16_t addr, String s)
...

uint16_t readUInt16FromEeprom(uint16_t addr, uint16_t & i)
...

uint16_t readStringFromEeprom(uint16_t addr, String & s)
...

// Write s in EEPROM, starting from address addr.
// Return the number of bytes written
uint16_t writeStructToEeprom(uint16_t addr, struct config_t s)
{
    uint16_t currAddr = addr;
    currAddr += writeStringToEeprom(currAddr, s.lastThing);
    currAddr += writeUInt16ToEeprom(currAddr, s.myIdx);
    return (currAddr - addr);
}

// Read s from EEPROM, starting from address addr.
// Return the number of bytes read
// S should be already allocated when entering the function
uint16_t readStructFromEeprom(uint16_t addr, struct config_t s)
{
    uint16_t currAddr = addr;

    uint16_t readVal = readStringFromEeprom(currAddr, s.lastThing);
    if (readVal == 0)
        return 0;
    currAddr += readVal;

    uint16_t readVal = readUInt16FromEeprom(currAddr, s.myIdx);
    if (readVal == 0)
        return 0;
    currAddr += readVal;

    return (currAddr - addr);
}

void setup(){
    readStructFromEeprom(ADDR, savedValues);
    Serial.println(lastThing);
}

String readString="asd";
void loop() {
    //...
    savedValues.lastThing = readString;
    savedValues.myIdx = 22;
    writeStructToEeprom(ADDR, savedValues);
}

I think that the idea is pretty easy to understand. Basically you manually write a function for each type you want to write (e.g. writeUInt16ToEeprom), then use these "building blocks" to create complex functions (e.g. writeStructToEeprom). For items which do not have a fixed width (Strings) you first save the length, then the bytes. What I mean with "fixed width" is that you know at compile time the number of childs it has For instance, the struct has two "childs" (the string and the integer), while the string has an unknown number of childs (n characters).
You can write a template function for all the integers like this:
// Write i in EEPROM, starting from address addr.
// Return the number of bytes written
template <class T> uint16_t writeIntegerToEeprom(uint16_t addr, T i)
{
    uint16_t currAddr = addr;

    // Only if there is enough space
    if ((currAddr + sizeof(T)) <= E2END)
    {
        // Write the bytes in eeprom
        for (uint8_t idx = 0; idx < sizeof(T); idx++)
        {
            EEPROM.update(currAddr++, (8*(i >> (sizeof(T) - 1 - idx))) & 0xFF);
        }
    }
    return (currAddr - addr);
}

// Read i from EEPROM, starting from address addr.
// Return the number of bytes read
template <class T> uint16_t readUInt16FromEeprom(uint16_t addr, T & i)
{
    uint16_t currAddr = addr;

    // Only if there is enough space
    if ((currAddr + sizeof(T)) <= E2END)
    {
        i = 0;
        for (uint8_t idx = 0; idx < sizeof(T); idx++)
        {
            i = i << 8 | EEPROM.read(currAddr++);
        }
    }
    return (currAddr - addr);
}

You can use it for all the integer types, using it like the UInt16 variant above. Avoid using it for classes or structs, since in some cases (e.g. the struct with string example above) it may not save what you want

but that is in the EEPROIM library as put() and get() for any reference. https://github.com/arduino/ArduinoCore-avr/blob/master/libraries/EEPROM/src/EEPROM.h

@Juraj are you saying that EEPROM put and get will allow to put and get the struct with the String? I doubt that. You can use "put" instead of the very last template implementation, but I don't think the rest of the answer must change

@downvoter: can you please explain why the -1? I think that the answer is on topic with the question (not declaration of the item), and moreover addresses the main problem with the OP implementation, which is the fact that he wants to save a string but he isn't actually doing so with his code

I am the downvoter.  No, you can't write String with put(), but your solution is not elegant and not tested. And we should discourage use of String.

I posted my answer

@Juraj Can you suggest how I can make it more "elegant"? About the not tested, did you check my code? Does it work? And finally, about the strings, they are not the "evil", they are instruments. I agree that whenever possible their use should be discouraged (as I wrote, I never used them, so I guess how they work and made researches but I don't have first hand experience), but sometimes they must be used

"elegant" would be effective use of library functions. you propose to add redundant functions to the sketch

Let us continue this discussion in chat.

it is better not to use String type at all and it can't be saved to EEPROM. You can save a copy of the internal c-string of the String with strcpy(savedValues.lastThing, readString.c_str());
#include <EEPROM.h>

#define ADDR 512

struct config_t {
  char lastThing[32];
  int lastNum;
} savedValues;

void setup() {
  Serial.begin(115200);
  Serial.setTimeout(10);

  EEPROM.get(ADDR, savedValues);
  Serial.println(savedValues.lastThing);
  Serial.println(savedValues.lastNum);
}

void loop() {
  if (Serial.available()) {
    String readString = Serial.readStringUntil('|');
    int n = Serial.parseInt();

    strncpy(savedValues.lastThing, readString.c_str(), sizeof(savedValues.lastThing));
    savedValues.lastNum = n;
    EEPROM.put(ADDR, savedValues);

    //clean rest of the input (crlf)
    byte b;
    while (Serial.readBytes(&b, 1) > 0);
  }
}

There are cases where dynamic allocation must be used. Personally I try to avoid it as hell, since these are microcontrollers and do not have plenty of memory, but in some cases you can't. Then you added a lot of assumptions to the code without highlighting. Do you know this project so well that you can assume that strings are separated by a pipe mark? Do you know that strings will never exceed 32 chars and you are so confident that you even don't check it? You are aware that if the user writes "This is a really wonderful day :)" you will have all sort of bad behaviors, right?

I replaced strcpy with strncpy. It is a test sketch for EEPROM, not a user friendly Serial input handling demo.


text:
Self made microphone burns Arduino
I'm very new to electrical engineering and I'm trying to read microphone input with Arduino Nano. I've made a separate microphone module (based on this example) and plugged it into Arduino like this:

Unfortunately it was the last time my Arduino was working. It's no longer displayed as a connection, and acts "randomly", so I think my microphone toasts controller for some reason. Here are some more pictures and a scheme of my mic module, could someone explain what am I doing wrong?

simulate this circuit – Schematic created using CircuitLab
R1 - CR1/4W 10 (brown,black,black,gold)
R2 - CR1/4W 2KO (red,black,red,gold)
I have no education in electrical engineering, so I'm not sure about the correctness of this schema of units, just pasted what's written on the pack

Your schematic shows R1 as 10k ohms.
Your color codes and description lists it as 10 ohms. 10K would be Brown, Black, Orange.
http://www.allaboutcircuits.com/textbook/reference/chpt-2/resistor-color-codes/
So R1 is the wrong value by a factor of 1000, you may want to fix that ;-)
As for damage to the main board, depending on the microphone used that may have put an excessive strain on the 5V supply pin. Does the power LED still come on at the same brightness as before? If not then the power supply regulator is probably toast. If it does then I'm not sure what the problem is, you shouldn't have broken anything else.


text:
Trying to read analog signal with digital pin using outside ADC
Is there a way to route an analog signal from a simple temperature sensor through an ADC, MCP3008, into a digital pin. I have used all the analog pins on my Arduino  Mega 2560 and am trying to utilize all the digital I/Os.
Any insights on the matter would be greatly appreciated.

The MCP3008 is an SPI device. You connect it to the SPI pins of your Arduino. Then you can read 8 analog channels through it.
It requires 4 pins: MISO, MOSI, SCK and a chip select pin.

If you don't plan on adding anything else that uses SPI you could just connect the ChipSelect to ground, and free a pin on the Arduino.

@Gerben That is not good practice. Chip Select is not just used to multiplex the bus but also to synchronise the start and (sometimes) the end of communication.


text:
How would I go about measuring an analog signal on my arduino mega that has both positive and negative voltages
I have a signal that fluctuates between -70mV and 50mV. How would I get the arduino to read this.. Ultimately I am trying to graph the data in real time so it looks like this.

https://i.sstatic.net/a8zIE.jpg

i don't think an arduino has much sensitivity (precision) between such close values. I would use an op amp to amplify it to ~0-5v, after it went through a voltage sum circuit, a dual op amp like the 358 will  let you do both with one chip.

You need to amplify your signal and add 2.5V as a "virtual ground" for the amplification. This gets a little tricky, since you need a low-impedance VCC/2 source to feed the amplifier as a virtual ground.  This would require a unity-gain buffer fed from a voltage divider:

simulate this circuit – Schematic created using CircuitLab
Now you use that to feed the amplifier:

simulate this circuit
The gain is set by 1+(RF/RG), or 11 in this case, giving you -0.77V to +0.55V.
There is a simpler option, though. (There is another intermediate option but the editor lost it and I can't be bothered to spend the time recreating it).
This method does come at a cost, though: it inverts the signal. The -0.07 becomes 0.07 and the 0.05 becomes -0.05, and multiplied by the gain and added to the offset:

simulate this circuit
Here you get a transformation from -0.07V - +0.05V to +0.7V - -0.5V.  That means that in software you then have to invert the value (simply subtract it from 0 after removing the DC offset).
You're basically shifting some of the complexity out of the circuitry and into the software.
Personally I use the inverting amplifier (the last circuit) because the virtual ground current is near zero, so you don't need a low impedance VCC/2 voltage source. It's also easier to create more sensible gains (like 10x) than the non-inverting amplifier, which always has 1 added to the gain.

Your second circuit doesn't have a well defined DC working point.

Quite possibly not. I was having a nightmare of a time with the editor. It kept wiping stuff out and crashing and deleting circuits.

@EdgarBonet The op-amp was upside down in the non-inverting second stage... oops...

Here is my try at this: if your voltage source doesn't mind sinking
something like 150 µA, you could try something like this:

simulate this circuit – Schematic created using CircuitLab
This should map the input range [−70 mV, +50 mV] to
[0.04 V, 4.06 V].


text:
Can you save data to EEPROM using firmata?
I have a few Arduino boards connected to my computer running firmata and I want the computer to be able to differentiate between them even when I unplug them and plug them back into a different USB port in a different sequence. My solution was to save and read a Unique I.D. into each Arduino's EEPROM, but I am not sure how to accomplish this using firmata?
I want to save a few bits of data to the Arduino UNO with EEPROM, but the Arduino has to be running code compatible with firmata. Is this possible?

What have you tried so far in you code? Have you tried using the adrunio eeprom write function with your arduino program -so once it knows the unique ID (in your arduino program) it writes it to the EEPROM using the command EEPROM.write(address, value) and the library EEPROM.h

Which firmata sketch for the Arduino are you planning on using?

I am using Standard Firmata Plus for one board and Standard Firmata Wifi for the other.

Currently, I've been putting a resistor in the first analog pin and Identifying the board based on that resistor value, I need a better way of doing this and I haven't been able to successfully find a method of saving to EEPROM via firmata.

You have to edit the Firmata source code and add a few lines of code:

add the EEPROM library
include the library into the Firmata code
in the setup() function use the EEPROM library to read the id from the EEPROM

How do you plan to write that data into your Arduino EEPROM?
If you want to do that via serial connection than you also need to add that code.
I have done something similar in an example for my VoltageReference library, specifically in EEPROMCalibration.ino
UPDATE
After a little investigation I understand there is the possibility to exchange generic messages and handle generic commands via Firmata: commands 0x00-0x0F are reserved for customization. On the Arduino side you can use:
void storeToEEPROM(int id) {
  ...
}

void readFromEEPROM() {
  char buf[12];
  Firmata.sendString(itoa(the_id, buf, 10));
}

void setup() {
  ...
  Firmata.attach(0x00, storeToEEPROM);
  Firmata.attach(0x01, readFromEEPROM);
  ...
}

That will allow you to write and read the id using those two custom commands.

Thank you for the response! Yes, that would allow the Arduino to have access to its ID stored in EEPROM, but I need to be able to read and write this data over Serial using the firmata protocol.

Please find the updated response: you can use two of the 16 reserved commands (0x00-0x0F) and attach your EEPROM reading/writing functions.


text:
a code problem for arduino GSM 1400 to send a SMS when tilt movment is detected using accelerometer
There is a mistake in the design implementation of the code probably in if statment - when using the serial monitor it repeatedly shows printf() statements from the code instead of "Sending SMS message".
 // Include the GSM library
#include <MKRGSM.h>
#include<math.h>
#include<stdio.h>
int xp = A5;
int yp = A4;
int x,y;
#include "arduino_secrets.h"
// Please enter your sensitive data in the Secret tab or arduino_secrets.h
// PIN Number
const char PINNUMBER[] = SECRET_PINNUMBER;

// initialize the library instance
GSM gsmAccess;
GSM_SMS sms;

void setup() {
    x=analogRead(xp);delay(2);
    y=analogRead(yp);delay(2);

  // initialize serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  Serial.println("SMS Messages Sender");
  pinMode(xp,INPUT);
  pinMode(yp,INPUT);

  // connection state
  boolean connected = false;

  // Start GSM shield
  // If your SIM has PIN, pass it as a parameter of begin() in quotes
  while (!connected) {
    if (gsmAccess.begin(PINNUMBER) == GSM_READY) {
      connected = true;
    } else {
      Serial.println("Not connected");
      delay(1000);
    }
  }

  Serial.println("GSM initialized");
}

void loop() {
    if ((x>=0.60) & (y>=40))

 Serial.print("AT+CMGF=1\r");
    delay(1000);
    Serial.print("AT+CMGS=\"+491781234567\"\r");
    char remoteNum[20];

  // sms text
  Serial.print("your bike is in danger!");
  char txtMsg[200];

  Serial.println("SENDING");
  Serial.println();
  Serial.println("Message:");
  Serial.println(txtMsg);

  // send the message
  sms.beginSMS(remoteNum);
  sms.print(txtMsg);
  sms.endSMS();
  Serial.println("\nCOMPLETE!\n");
   delay(5000);
   if ((x<=0.30) & (y<=25))

 Serial.print("AT+CMGF=1\r");
    delay(1000);
    Serial.print("AT+CMGS=\"+491781234567\"\r");

  // sms text
  Serial.print("your bike is in danger");
  Serial.println("SENDING");
  Serial.println();
  Serial.println("Message:");
  Serial.println(txtMsg);

  // send the message
  sms.beginSMS(remoteNum);
  sms.print(txtMsg);
  sms.endSMS();
  Serial.println("\nCOMPLETE!\n");
   delay(5000);
}

If that is a real phone number you should redact it, also you should have edited your other post instead of posting a new question.

you already asked this question .... please update your previous question and delete this one .... Problem with code for arduino GSM 1400 to send a SMS when tilt movment is detected

Nowhere in your code will it print "Sending SMS message". It should print "SENDING Message: ". Please paste in the serial output that you are actually seeing, rather than describing it - in your original post rather than this duplicate..

Your if statement is broken!
if(cond)
   statement; // this is conditional
statment2; // this will always be executed!

You need to use a code block:
if(cond)
{
    statement; // both statments are now
    statement2; // conditional!
}


text:
Why is my Arduino is getting power from the 5V pin?
I have an Arduino that is controlling two 6V DC motors through a L298N motor driver. The motor driver is being powered (from its Vin pin) by a 7.4V external source.
I then have the 5V pin from the motor driver connected to the 5V pin on an Arduino UNO to power the logic board.
Now, when I plugged in my Arduino to my computer to upload the sketch, everything was fine. However, when I unplugged the Arduino from the laptop, the Arduino was still being powered somehow from the 7.4V external source, though that source should only be powering the motors. I thought that unplugging the Arduino from the laptop would have cut power to the Arduino, but it was still somehow being powered by the external source.
What is going on here?

What is going on here? ... we can only guess ... you provided almost zero information ... please draw a clear diagram of all of the connections

@jsotola I added a diagram.

How about a schematic the frizzy picture does not help me much as I do not recognize the motor board.

It could be that this driver board is designes to supply (rather than consume) power through its 5V pin. Do you have a reference to this board?

What @EdgarBonet said is the most plausible scenario. It appears that at least some L298 modules have a jumper selectable 5 volt regulator which can be used to supply the 5 volt logic side of the L298 chip but only if the motor side voltage is less than 12 volts. If the motor voltage exceeds 12 volts, the jumper must be removed and the L298 module 5 volts must be supplied from the MCU board. See the example here: http://wiki.sunfounder.cc/index.php?title=Motor_Driver_Module-L298N . TL;DR ? understand and check the module jumpers.

@EdgarBonet its an Elegoo Uno R3

The Arduino Uno can be powered from the 5 volts present on the USB cable or from an external 5 volts connected to the Arduino's 5V and GND (ground) pins.
In general, power supply outputs should never be connected in parallel unless they are designed for such an unusual configuration. From the description in the Question, it appears the USB power and the L289N power supplies were connected in parallel. Fortunately, the Arduino design include a power cut off shich.  Look for part "T1" in this schmatic.  If power is applied from both the 5V pin and the USB port, the 5V pin is used and the USB power is cut off.
To answer your question specifically:

Assuming this is your board's schematic (note, this is a link to an RAR file which contains a JPG of what is likely the wb291111 board's schematic) and assuming you have J6 jumper installed.

If the Arduino 5V and GND (ground) pins were connected to the L289N board and the L289N board was supplying 5V power to the Arduino board, the Arduino board was never powered from the computer's USB port as transistor "T1" would have disconnected the USB power from the Arduino.

Is there another configuration to send 5V to the motor driver logic board? The plan was to have a separate 5V power supply for the Arduino, and have the Arduino send power to the logic board on the motor driver. The 7.4V external source is only to power the motors.

It looks like disconnecting J6 will remove the source of power of the motor driver board's 5V regulator.  Test this (the "disconnected" 5V pin of the motor driver board) with a volt meter ... as the schematic is a bit hard to read (doesn't look correctly labeled).  But why use 2 power supplies if you can get away with only 1 (the motor driver board power supply)?


text:
Confusion re: getting bootloader onto new-out-of-the-box Nano v3.0 (classic)
I've been trying to do a sort of "crash course" in Arduino but there's something I'm still confused about.
I've read about programming ATTiny microcontrollers using Arduino boards, and I've decided to get a Nano v3 from the official Arduino site (too many clones seem too glitchy to me).
All I want (for now) to do is, Stick it into a breadboard and connect it to an ATTiny, so that I can use the MCU (to create LED effects).  So, for now, I just want to use the Nano as an "ISP".
Anyway, one thing I have not yet seen clarified is,
How does a user put the "bootloader" onto one's first, new, just-out-of-the-box Nano (or really, any Arduino board) when there is no previous board to use to do that...?
I personally don't understand why they don't come with the bootloader already installed, but they don't as far as I can tell.  So, do I just plug the Nano (or other board) into the USB port, and open the Arduino IDE, and then the board will automatically "understand" the IDE?  Or is there something else that has to be done first? (By "first", I mean, aside from installing, and opening, the IDE ;) ).
Sorry for such a basic question but I simply have not seen this clarified, and I can't spend money on a Nano just to find out that I need some expensive widget to put the "bootloader" onto it...

a new Nano has a bootloader

All new Arduinos should all have bootloaders pre-installed. FWIW, I have only ever purchased clone Arduinos (Nanos, Unos, Megas, Micros, Leonardos, whatever). for over 9 years, and never had any problem, "glitchy" or otherwise, what so ever.

To add more: that the boards broadly have bootloaders is a notable "element" of what makes the original Wiring (Arduino's heritage) approach its intended goal "to make it easy for artists and designers to work with electronics, by abstracting away the often complicated details". To have, connect, and use a separate programming device being one of those details. Using attiny devices (usually) without bootloaders is more the exception than rule in the space of things "Arduino".

Thank you very much for your replies, Juraj, Greenonline, and Timemage!
I honestly either did not see that info before, or else just didn't get that from the info I saw.  That's specifically true of Timemage's example - I've seen similar info, but I just was not able to distill the detail re: the bootloader from it... I know that I'm far too literal sometimes, so I looked for, and didn't find, a specific mention
So Thank You for your patience and your answers!

@Greenonline - Thank you for that info about the clones, BTW.  I've been looking at Amazon reviews (I know - not the best but they do have a generous return policy...).  I'll give them another look if they're actually reliable.   I was focused on the ones that have the Atmel ATmega328P chip (the ones that do have it, mention that, and show it in the product photos), so maybe that's the main thing.  I dislike being so focused on keeping to a shoestring budget but the clones are definitely more "shoestring compatible", Heh ;) -- Anyway, thanks again!

Buy from AliExpress or Ebay (direct from China) for a dollar (at least less than $5). Maybe buy bulk (3 or 10 units) to keep the price down. You can even get them without the horrific CH340 IC if you pay a dollar or two more (per unit).

Hello, Greenline, Interesting info, again, thank you - tho' to be honest, I'm very leery of ordering from China.  Plus, I'm confused - I know that the the CHC340 allows the board to connect to the computer via USB, tho' I've also read many cmplaints about it, so do I also need to get - let me check - an "FT232RL Mini USB to TTL Serial Converter Adapter Module"...?   At which point, shouldn't I just bypass the Nano completely and directly program the microcontroller to control the LED(s)...?

It's kind of difficult to get you guys (Stack Exchange regular contributors) to actually answer questions in the answer box, is it not? It is no small feat to cause that to happen. I have taken the bull by the horns and answered it for you.

Indeed all Nanos should come with a boot loader. There is a lot of discussion about missing drivers on the PC for the USB chips (of which there is a variety in use) on the Arduino boards. This is not exactly the same thing and less likely with an official Arduino product. BTW, the new series ATtinys are not programmed using the ISP method instead using UPDI so the Nano is less relevant  but that is a separate topic. Incidentally, you may anyway want to upgrade the bootloader on the Nano, effectively making it a Uno, and gaining 1.5k more flash memory for your sketches. Again another topic.

Thank you,  6v6gt - that was, in fact, a part of my confusion.  Thank you also for the Nano's bootloader can be upgraded!   Re: programming the ATTiny, I'll keep your note in mind if I look at newer items; I ordered the'85 and the '44 because I found a good bit of information about programming those with Arduino.  This will be my first foray into this so I'm going for something totally basic to start with...

All the Arduinos that I am aware of come with a bootloader pre-installed. They wouldn't be much use, would they, if you had to buy a second Arduino to put the bootloader on the first one, and then buy a third one to put the bootloader on the second one, and so on. You would end up buying an infinite number of Arduinos!
The whole idea of the Arduino was to let students get into programming microprocessors with a minimal expense in hardware, which is why they come with a USB interface and a pre-programmed bootloader.
In the event that you buy an Atmega328P chip from eBay without a bootloader on it, I have code that lets you use an existing Uno or similar to program it.
This lets you make a minimal board for only a couple of dollars - the price of the chip, and a handful of extra cheap components.

Thanks, Nick!
I don't yet know how or why answers/comments end up where they do; I just try to read through everything ;)   Be that as it may, thank you for your answer - what you wrote makes sense, but some of the 'how to' articles I read seemed to contradict that.  Based upon the answers here, though, my confusion was apparently just my lack of familiarity with how things are worded in the "Arduino World".  Every discipline has its own "dialect" to learn...
The idea of making a board is interesting, and thank you for the code link, but that's way beyond my Total Noob level for now ;)


text:
System voltages: Can I use a 5V touchscreen shield on a 3.3V arduino?
The system voltage on my arduino 101 is published at 3.3V, even though it also has a 5V output pin.
My Seeedstudio touchscreen is supposedly a 5V device. http://wiki.seeed.cc/2.8inch_TFT_Touch_Shield_v2.0/
I believe I've successfully ported the library for this touchscreen to the 101 because it now runs and compiles on both the 101 and the Mega, although it gives erroneous values on the 101. Could it be because of this voltage difference? is there any way to fix it?
Edit- I should add that the 101 is labeled as "5V tolerant".
Edit II: I've found a pretty informative review that explains a little bit about how the 101 is supposed to work with 5V peripherals. I'm not sure though how it could work in cases where a shield does not recognize 3.3V as logic high. Usually 3.3V is right around the cutoff voltage for many circuits. http://www.tweaktown.com/reviews/7706/intel-curie-based-arduino-101-programmable-microcontroller-review/index2.html

You'll probably need a fairly common device known as a logic level converter.  One such example, in breakout board form, can be found here: https://www.sparkfun.com/products/12009
There are tons of other options depending on what exactly you need.

For what it's worth, I connect the transmitter output of a 3.3v WiFi radio (ESP8266) directly to an input pin on a 5v Arduino. with reliable results. 3.3V is high enough to be recognized as a (5v) logic HIGH. You will need a level conversion going the other way, 5v -> 3.3v, however.

That's not necessarily true.  Logic HIGH typically has a range of values that are acceptable, and many chips are designed to be 3.3V or 5V tolerant.  However, only the datasheet will tell you if a 3.3V logic level will be interpreted as HIGH.

Thanks Michael. Part of my question is whether the touchscreen chip recognized 3.3V as High. According to the datasheet, that would seem to be the case. But my results suggest otherwise. I've got the same code running on the 101 and the Mega, but the screen only shows white backlight on the 101, and the touchscreen output numbers are all out of whack. And unfortunately, I'm not sure I can implement a logic level converter because I don't have room to do anything between my SPI headers. The touchscreen shield fits right on top of the 101 board.

For a 5V CMOS device a logic high is typically 3.5V (about 0.7xVcc). For a TTL device it's about 2V.


text:
"return" not working to break out of a loop
I'm fairly new to this, and I haven't been able to find any answers after searching repeatedly.
I have a Startscreen() function that I run during my setup sequence, and within that function i use various while loops and if/else conditionals. This function runs the startup screen of my program on my touch screen.
Well, when certain conditions are met inside a switch case, inside a while loop, I want to load my main screen and then immediately stop the whole Startscreen() function, like this:
LoadMainScreen();
return;

However, I end up seeing my main screen load up, and then my Startscreen() function continues!
Apparently, "return;" does not work as advertised. If I wanted to break out of the current loop, I'd use "break;", right?
So my question is, does it matter that I'm using return; inside a while loop, inside a switch case? How do I exit the whole top-level function completely?
I already tried breaking out of the function and going straight to my main loop this way:
LoadMeasScrn();
loop();
return;

and the same thing happens.
So here's (most of) my entire code:
//////////REMOVED/////////THANKS FOR YOUR ANSWERS/////////////

It's impossible to say from those tiny snippets. We need to at least see the structure of your whole code.

Well, I can't post my code. It's 800 lines long, anyway, so I doubt anyone would want to sift through it. Not sure what I could do to better explain the situation. This is more of a question of how the return function is supposed to work.

At the very least show us how and where those functions are being called.

Return does what it says it does. The problem isn't with the return - it's either with how you are using it, or the rest of the structure of your code.

Not here! In your question!

Ok, I'll try with some pseudocode in an update

At first glance that structure looks fine. Are you sure the board isn't crashing and resetting? Maybe due to lack of memory?

Your second outermost if() clause in StartScreen(), the one that begins with if (frametype == 0 || frametype == -1), contains an infinite while loop. That loop contains no break statements, and calls StartScreen() -- it recurses into itself!
Without my trying to follow the program logic, I can at least posit that the code is in a second or higher recursion when it calls return, thus returning to where it had called itself. So, yes, if that is correct, it will still be executing within StartScreen() after the return statement. The return statement wouldn't have "failed" in that case; it would have resumed the at the point where the its prior instance called itself.
If that sounds convoluted, it's because it is! There can be good reasons to recurse, if you intended to, your know in what circumstances the code will recurse, and you know that recursiing will stop before you run out of stack space. Carefully review your program logic; this may not be one of those instances....

I follow you. I replaced the recursion cases with something else I found. I'm now using a label at the very beginning of startscreen()
`startover:`

I'm then calling goto startover; Does this effectively start the function over at the beginning without the recursion problem?

Yes, that's quite different to recursion. Did it alter or help with the original issue?

I think so! It had not occurred to me before that the program had gone back to a previous instance of startscreen(). Looking back though, I can see where it might have occurred without me knowing.

This part is wrong, for a start:
LoadMeasScrn();
loop();
return;

That would recursively call loop (which you almost never want to do) effectively putting you into loop a second time.
return does what is advertised to do. Your rather complex pseudo code demonstrates nothing. Please post a Minimal, Complete, and Verifiable example

It's 800 lines long, anyway, so I doubt anyone would want to sift through it

I would much rather read 800 lines of code than try to guess what you are doing.

You have an incredible amount of recursion. You possibly think that if StartScreen calls itself then it goes back to the start (like a goto) but no, you are now two levels deep into StartScreen.
Plus here:
void StartScreen(void) {
...
  if (stuff)
...
                Recheckframe();

...
bool Recheckframe(void) {//For use in start screen, function rechecks frame
...
  if (otherstuf)
...
        StartScreen();  //Start all over
        }

It's a wonder it doesn't just crash by running out of RAM.
You say "//Start all over" but it isn't starting all over. You are now digging deeper and deeper into the call stack.
Your call stack will look something like:
StartScreen -> StartScreen -> Recheckframe -> StartScreen

You need a rewrite, frankly. A state machine would probably be very appropriate.

Alright, fine. Hope I don't get fired.

See amended answer.

Incredible recursion!!!!!!!!!


text:
Can I connect my arduino ground to an external battery ground? Are they the same when said battery is powering the arduino?
I need to power my camera peripheral with an external power supply, since apparently I can't power both the camera and the camera's relay switch with my 5V out pin (My relays cut out and continually reset themselves if I try to run my 5V to both the camera relay switch and the relay board VCC.)
So I'm powering the camera with a 5V battery pack and my arduino with my PC, but I still need to communicate with it via UART, so I need the camera ground to be the same as my arduino ground. Can I connect the two? Is this a bad idea? Because I'm doing it now and it seems to work. I just don't want to cause a problem later on down the road, whether I'm connected to my computer or on battery power.Any advice would be greatly appreciated.

A battery's ground is floating. That means that it's "happy" to take on any absolute value by simply connecting it to another ground - it just stops floating. This is why it's easy to connect a battery-powered phone directly to a computer to get the photos off or whatever.
The only time you shouldn't connect two grounds is if neither are floating. A good example would be the grounds of two different houses, which are physically connected to the Earth (as in the planet). It'd be difficult to budge the whole Earth's ground level!
But shouldn't they be the same? Unfortunately not. You could measure a distinct voltage difference (sometimes in the hundreds of volts) between two house earths due to the differences in their makeup.
One small note: if you do connect two grounds, only connect them in one spot. If you have two other ground pins a small distance away from the connected ones, there may be a voltage difference between them: now the two are explicitly relative to each other, so neither can be considered floating relative to each other. The pair as a system - if neither are earthed at least - is still floating.
These so-called "ground loops' can induce current where none is desired.

Outstanding answer. I guess I never realized this happens every time I plug a phone or a camera into a computer!


text:
How to use BNO055 via HIT over i2c
We are using the Arduino Nano board and connected the Bno055 sensor to it via HID over I2C (hereinafter simply HIT). For the purposes of the academic project, we need to figure out how to program the sensor via this interface, not via the usual I2C.
There is very little information about this on the Internet. The most popular Adafruit library for this sensor, as I understand it, does not support HIT. I have not found a single library that supports this interface.
We also found out that the standard Wire library for I2C does not support HIT either. We will be grateful for any help.

Sounds like you choose a wrong MCU (Arduino Nano doesn't have a USB/HID peripheral) and a wrong sensor. Maybe you should clarify with your teacher. If you are interested on the I2C HID, you can take a look at those Hackaday blogs here and here, or the Linux source code.

@hcheung, You didn't quite understand what I meant. If only the PS0 jumper is connected to the ground, then the BNO055 sensor, according to the BOSCH documentation, operates via the HID over I2C interface. Then its address is 0x40. How do I work with this address?

To be clear, you want to operate it in HID over I2C mode (PS1=0;PS0=1) despite the fact that it will be significantly easier for you to use in the more conventional I2C mode (PS1=0;PS0=0)?

here is more information https://forum.arduino.cc/t/how-to-use-bno055-via-hit-over-i2c/1336233 ... it appears that the OP has been tasked to write a driver

I'm not aware of any Arduino libraries or tutorials to do HID over I2C. I was curious enough to learn quite a lot about it from the ground up about 9 months ago. It's just too involved to want to turn into an answer on here. You'd need the main documentation to HID over I2C. This will only make sense in light of an understanding of the normal USB HID, HID usage tables, etc. It is also rather pointless and painful to choose it over the normal register-based I2C BNO055 interface without good reason.

@jsotola, I am the author of this post

@timemage, This is the goal of the project