text:
Can pin mode damage Arduino with connected electronics?
I am not that experienced with electronics, so this might be a silly question. But I dont know. Assume that I have connected some electronic circuit (transistors, leds, anything else) to the Arduino pins, is there any chance that I damage the hardware if I change the pinmode to input? What role do the integrated pullup/pulldown resistors play? Basically, is it possible to create some "unintended" flow of current, that damages the board or external hardware, if I change the pinmode or disable/enable the pullup/pulldown resistors (or something else that I dont know about)? Can I break the hardware by programming mistakes?

yes ... if you change pinmode to output and set output level that causes large current to flow

General rule: connecting input to input or input to output is ok. Connecting output to output is bad and can kill electronics.

You are coming with some good questions about a complicated subject. You will be going through a learning process. If you do not violate the design parameters of the micro (voltage and current to name a few) you normally will not damage it. Knowing all of those parameters and what the circuirity surrounding the micro has a huge impact on your what can damage your micro and design. Without a schematic, this will change with each circuit and integration, it is impossible to give a definitive answer but I will take a SWAG.
Question: "is there any chance that I damage the hardware if I change the pinmode to input?"  and it depends on what mode the pin is in before you change it and what is connected to the pin. Generally you will not damage it assuming your voltages are equal to or less then the voltage supplying the microprocessor and the pin is not connected to an inductive component. You can get changes in your external hardware.
You ask "Can I break the hardware by programming mistakes?". Again I cannot give a definitive answer unless the circuit and what is connected is known. LEDs etc are generally no problem. If in doubt place a resistor in series with the load, something in the range of 330 to 500 ohms and see what happens. If you turn on some external device that damages stuff that is one possibility.
You ask: "if I change the pinmode or disable/enable the pullup/pulldown resistors..."Probably not but it depends on what is connected to the pins. Generally if the pull up resistors are needed such as for a button turning them off will cause some intermittent problems where it is on then off but that will not damage the micro, the effect on external devices is unknown as are the devices.
This stuff is not going to be assimilated in a few days but over a much longer period. There is always more then one way to do a project, the best is probably what you decide. You will make mistooks, and possibly destroy some of your Arduinos, this is to be expected, that is why I have spares. The most important part of the process is to enjoy and have fun.


text:
Can a power cut damage the software?
When unplugging the power source of a device that is writing some data "A" to an SD card, also other data "B" might get corrupted. (This is detailed here.)
Regarding Arduino projects without an SD card, is it OK to remove the power source of Arduino microcontrollers anytime because the memory inside them uses a different technology than SD cards do (what are the names or differences of the respective technologies)?
Or are there several entirely independent memories - one for data and one for software/sketches?
Or do Arduino projects have to be programmed such that there are periods without data-writing and an LED indicates when it is safe to cut off the power?

First we need to look at the different memory technologies in a microcontroller:

First you have the flash memory. This is where the program is saved, but it can also be used to hold user data. On AVR based Arduinos it can only be written while programming or by the bootloader. But boards like the various ESPs can also have a little file system in it. Here you can get problems with a power loss while write operations happen.
The RAM holds the current value of all variables. But it also always looses all data when unpowered. This is normal behavior because it is volatile memory. A power loss won't change anything here.
That leaves us with EEPROM, a non-volatile memory type. You can corrupt your data with a power loss during write operations.

Then we need to look at the data structures. Most memory in Arduinos and similar boards a organized as a simple array of bytes. EEPROM is usually handled this way. If you write a data structure and have a power loss during that time, you must view this data structure as corrupt (for example writing a string with 20 characters, but while writing the 6th byte the power goes out). Other data is not harmed. On the other hand when you use a filesystem in flash like SPIFFS a write action in a file also involves handling a filesystem table. Outage during handling of the table might corrupt your filesystem integrity, thus can also harm other files.
SD cards are a special case, since their internal controllers move the data around to some unknown algorithm to implement wear leveling. This is not done with standard microcontrollers (you would need to implement it yourself if needed). The actual memory technology is also just flash, but you don't want to disturb the SD card while its handling its wear level algorithmus. That might corrupt the SD card completely. Also the linked answer talks about the SD card of a Raspberry Pi, which has a complete OS running on it. Running an OS involves way more changing non-volatile data than a microcontroller typically needs. So its way less likely to have the same situations with a microcontroller.

Or do Arduino projects have to be programmed such that there are periods without data-writing and an LED indicates when it is safe to cut off the power?

Normally that is not needed, though it depends on your application and how the sketch handles the data. Are you saving data to non-volatile memory? How often do you do it? How often do you cut the power? If you are writing to byteswise memory like EEPROM, can you tolerate specific data corruptions? How much data are you writing each time?
Without assessing all these questions you cannot really say. Typically beginners just start without precaution in that direction. When you see problems after replugging, then you still can add an activity LED to the project.

TL;DR If the sketch doesn't write to non-volatile memory, it is safe to pull the plug at any moment.

Thanks! Regarding "Outage during handling of the [filesystem] table": I guess "handling" means writing. So if I want to regularly write some data A1, A2, A3 and avoid damaging existing data "B", is it good to allocate one big empty file "A" and regularly write data into it (kind of a "filesystem within a filesystem"), instead of regularly creating several small files?

source: Stack Exchange

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

sort: votes


text:
Porting Arduino for ATMEGA16U2
I have a bunch of ATMEGA16U2 in my drawer and I need to make a small production of custom boards with Arduino-based firmware.
After a Google search I learn the ATMEGA16U2 is often hosted on the Arduino boards as USB converter and there some hacks to reprogram it. But this is not my goal... I'm trying to understand how to compile and download the firmware using Arduino IDE and this MCU as target.
I guess (also from this old question) I need to update both the bootloader and the specification of the board.
Questions:

before reinvent the wheel are you aware of a ready-to-use porting for ATMEGA16U2? I did a search find nothing relevant

what is the official guide to update the files (bootloader + boards.txt) to support a new MCU? I find forum threads only

this could help https://arduino.stackexchange.com/questions/54484/adding-a-custom-board-to-the-arduino-ide/60660#60660 using AVR core as referred core

@Juraj thanks I'm reading the answer - but as said it's again a public forum... where is the official documentation that explains in detail each step?

there is a link in the answer to the official doc, but there is no tutorial

@Juraj I saw but it's about arduino-cli. If it's correct I'm going to study it :)

Arduino IDE uses the arduino-cli

Ok, because it's not installed by default I didn't understand that.

I don't agree with the decision of closing the question. Actually, my questions are precise and different than what reported in the other answers.

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


text:
How to modify an Arduino Due native USB port VID and PID?
I would like to know if it is possible to modify the VID and PID of the Native USB port of an Arduino Due.

in C:\Users\<user>\AppData\Local\Arduino15\packages\arduino\hardware\sam\<version>\boards.txt. but better create a custom definition this way

No wait, probably I did not write it correctly. I would like to set up the native USB to have a different VID or PID from the current one VID_03EB PID_6124.

the values from boards.txt are used in the USB handling part in the uploaded sketch


text:
Where does the 5v Output power on the Arduino uno come from?
I am wondering where the extra 5v output power on the Arduino uno come from. Is it directly from the atmega328 microcontroller or from the external power source (usb or 9v battery). Thanks.

If you are connected to USB then it comes direct from the USB port's 5V.
If you have an external power supply connected (either to the barrel jack or to the VIN pin) then it comes from the onboard 5V regulator.
The only thing that ever comes from the ATMega chip is digital signals.


text:
Arduino fast ADC sampling--which burst control is best?
If one wants to do quick bursts of free-running ADC conversions, should one pause and restart using:
The ADC enable bit: bitClear(ADCSRA,ADEN) & bitSet(ADCSRA,ADEN),
The interrupt enable bit bitClear(ADCSRA,ADIE) & bitSet(ADCSRA,ADIE),
The start conversion bit bitClear(ADCSRA,ADSC) & bitSet(ADCSRA,ADSC),
The auto-trigger enable bit bitClear(ADCSRA,ADATE) & bitSet(ADCSRA,ADATE),
or do you need some more complicated combination of the bits?
Here's some code where I'm trying to trigger a pulse and  burst of samples and then report back to the host computer:
const int numSamples = 20;
const byte startPin = PD0; // start signal (pullup)
const byte pulsePin = PD6; // Normally low
const int pulse_us = 10 ; // output pulse length

int16_t sampleData[numSamples];
volatile int sample;
unsigned long t0, t;

// state machine:
typedef enum { STATE_NONE,  // idle
               STATE_SAMPLING, // record ADC
               STATE_DONE, // report data
 } states;
// current state-machine state
volatile states state = STATE_NONE;

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

  pinMode(startPin,INPUT_PULLUP);
  pinMode(pulsePin,OUTPUT);
  // Clear ADC
  ADCSRA = 0;
  ADCSRB = 0;
  ADMUX = 0;
  ADMUX |= (0b0000 << MUX0); // Choose ADC channel 0
  ADMUX |= (0b01 << REFS0);  // Choose VCC reference voltage
  bitSet(ADMUX,ADLAR);  // ADC left align ADC result into ADCH register

  // sampling rate is [ADC clock] / [prescaler] / [conversion clock cycles]
  // for Arduino Uno ADC clock is 16 MHz and a conversion takes 13 clock cycles
  //ADCSRA |= (0b101 << ADPS0); // /32 : 16M/32/13=38461Hz 26us
  //ADCSRA |= (0b100 << ADPS0); // /16 : 16M/16/13=76923Hz 13us 10 bit precision
  ADCSRA |= (0b011 << ADPS0); // /8  : 16M/8/13=153.8KHz 6.5us low precision
  //ADCSRA |= (0b010 << ADPS0); // /4  : 16M/4/13=307.6KHz 3.2us lower precision
  //ADCSRA |= (0b001 << ADPS0); // /2  : 16M/2/13=615.4Hz 1.6us  bad precision

  ADCSRB |= (0b000 << ADTS0); // Choose free running trigger mode

  bitSet(ADCSRA,ADATE); // enable auto trigger mode per ADSCRB:ADTSx
  bitSet(ADCSRA,ADIE);  // enable interrupts when measurement complete
  bitSet(ADCSRA,ADEN);  // enable ADC
  bitSet(ADCSRA,ADSC);  // start ADC measurements

}

ISR(ADC_vect) // Record samples
{
  sampleData[sample++] = ADC;  // read 10bit value from ADC
  if (sample >= numSamples) {
    bitClear(ADCSRA,ADEN); // stop recording
    state = STATE_DONE;
  }
}

void report(){
  t = micros()-t0;  // calculate elapsed time
  Serial.print("Sampling frequency: ");
  Serial.print((float)1000000/t);
  Serial.println(" KHz");
  for (int i = 0; i < numSamples; i++){
    Serial.print(i);
    Serial.print(' ');
    Serial.print(sampleData[i]);
    Serial.println();
  }
}

void startSampling(){
  sample = 0;
  t0 = micros();
  digitalWrite(pulsePin,HIGH);
  bitSet(ADCSRA,ADEN); // start ADC
  delayMicroseconds(pulse_us);
  digitalWrite(pulsePin,LOW);

}

void loop()
{
  switch (state){
    case STATE_NONE:
      if(digitalRead(startPin)==LOW){
        startSampling();
        state = STATE_SAMPLING;
      }
      break;
    case STATE_SAMPLING:
      break;

    case STATE_DONE:
        report();
        state = STATE_NONE;
        break;
    default:
    ;;
  }
}

Toggling ADEN was my first thought, but ADIE seems as if it would be faster, and ADSC seems cleanest, if it works to modulate free-running ADC mode.  Which would be fastest and cleanest?
I have a Nano on order, but nothing available for testing right now.

Using ADIE could give you faulty readings, as you could get an interrupt for a AD-conversion that started before you enabled the interrupts. Using ADEN will make the first conversion take longer, which you might not want. I'd set/clear the ADATE bit. Alternatively, is timing isn't that critical, you could keep the ADC running, and set sample back to zero, when you want to start recording a new set of measurements.

Thanks.  I hadn't considered ADATE.  I think I might need to do more than one bit, one to stop the next interrupt, and others to clean up the status on the first capture of the next cycle.  And protect the samples better in the ISR.

@Gerben -- Yes, letting the ADC run on automatic and toggling the sample recording seemed cleanest.

After some bumbling around, several bit are important:
ADCSRA &= ~(bit(ADATE) | bit (ADSC) | bit (ADIE)); // Disable

ADCSRA |=   bit(ADATE) | bit (ADSC) | bit (ADIE); // Enable

The interrupt enable bit bitClear(ADCSRA,ADIE) & bitSet(ADCSRA,ADIE), would stop the current ADC measurement from triggering an interrupt event.
The auto-trigger enable bit bitClear(ADCSRA,ADATE) & bitSet(ADCSRA,ADATE), triggers a new conversion as soon as the current one finishes.
The start conversion bit bitClear(ADCSRA,ADSC) & bitSet(ADCSRA,ADSC), is important for kicking off the first conversion.
The ADC enable bit bitClear(ADCSRA,ADEN) & bitSet(ADCSRA,ADEN), turns the ADC subsystem on and off, but there is a bit of a delay on start up.
Ultimately I left free-running automatic ADC enabled and switched the data recording on and off using the ADCSRA&bit(ADIE) as a "BURST" state variable.  I think this is good enough for generic impulse-response testing:
//: ArduinoPulseADCSample.ino -- Pulse a pin and sample response on ADC
// For Arduino Uno/Nano/mega
// https://github.com/drf5n/foxyPulseInduction_Discrimination/tree/discrimination/ArduinoPulseADCSample
// Adapted from  http://www.gammon.com.au/forum/?id=11488&reply=5#reply5
//          and https://github.com/pedvide/ADC/tree/master/examples/analogContinuousRead
//
// This code emits a digital pulse on A1 and collects a sample of highspeed ADC from A0
// It sets up a free-running ADC to quickly record a set of ADC data in
// response to the pulse.  The size of the pulse, pins, number of samples,
// speed of sampling, etc... are all configurable.
// The ADC interrupt handler controls the pulse length and filling the sample buffer
//
// Serial Commands:
//
//  *  Write v and press enter on the serial console to get the value
//  *  Write c and press enter on the serial console to check that the conversion status,
//  *  Write s to stop the conversions, you can restart it writing r.
//  *  Write r to restart the conversions.
//  *  Write p to emit a pulse and record a burst of values
//  *  Write d to see the data recorded during the burst (compatible with SerialPlotter)
//  *  Write m to see metadata about the sample size and interval
//
//  Loopback test with a jumper or RC network between A1 and A2.
//

// Configurables:
const byte adcPin = 0; // A0 -- Pin to read ADC data from
const byte pulsePin = A1; // Next to A0 -- pin to pulse
const byte oneshot_pin = 12; // OC1B pin on Mega, controlled by Timer1
const int pulse_us = 50; // pulse duration
const int numSamples = 20; // sample set
// Change the sampling speed with the prescaler config in setup()

volatile uint16_t samples[numSamples];
volatile int sample = 0;    // position in sample state variable
#define BURST (ADCSRA & bit(ADIE)) /* Sampling burst state variable */
int adcReading;
unsigned long sampleEnd;
unsigned long pulseStart, pulseEnd;

// ########## Timer1 One-shot functions
// The one shot pulses are output on Digital pin OC1B (Arduino Uno D10, Mega D12, Nano D3)
// Modified by Dave Forrest 2020-01-11 for Timer 1
// Based on Josh Levine's Nov 23, 2015 work at https://github.com/bigjosh/TimerShot/blob/master/TimerShot.ino

// Setup the one-shot pulse generator and initialize with a pulse width that is (cycles) clock counts long
#define OSP_SET_WIDTH(cycles) (OCR1B = 0xffff-(cycles-1))
void osp_setup(uint16_t cycles) { // 1 idles, 0xffff never matches, 2-0xfffe makes pulses
  const byte prescaler = 0b010; // Choose /8 for 0.5us resolution
                                // 0b001: /1,      16MHz, 62.5ns resolution, 4ms max
                                // 0b010: /8,       2MHz,  0.5us resolution, 32ms max
                                // 0b011: /64,    250kHz,  4us  resolution, 263ms max
                                // 0b100: /256,  62.5kHz  16us  resolution, 1.048s max
                                // 0b101: /1024, 15625Hz, 64us  resolution, 4.194176s max
  TCCR1B =  0;      // Halt counter by setting clock select bits to 0 (No clock source).
  // This keeps anyhting from happening while we get set up
  TCNT1 = 0x00;     // Start counting at bottom.
  OCR1A = 0;      // Set TOP to 0. This effectively keeps us from counting because the counter just keeps resetting back to 0.
  // We break out of this by manually setting the TCNT higher than 0, in which case it will count all the way up to MAX and then overflow back to 0 and get locked up again.
  OSP_SET_WIDTH(cycles);    // This also makes new OCR values get loaded frm the buffer on every clock cycle.
  TCCR1A = 0b11 << COM1B0  | 0b11 << WGM10; // OC1B=Set on Match, clear on BOTTOM. Mode 15 Fast PWM.
  TCCR1B = (0b11 << WGM12) | (prescaler << CS10); // Start counting now. WGM 15=0b1111  to select Fast PWM mode
  // Setup the OC1B pin for one-shot output:
  //DDRB |= _BV(2);     // Uno Set pin to output (Note that OC1B = GPIO port PB2 = Arduino Uno Digital Pin 10)
  DDRB |= _BV(6);     // Mega Set pin to output (Note that OC1B = GPIO port PB6 = Arduino Mega Digital Pin 12)
  //DDRD |= _BV(3);     // Nano Set pin to output (Note that OC1B = GPIO port PD3 = Arduino Nano Digital Pin 3)
}

// Setup the one-shot pulse generator to idle:
void osp_setup() {
  osp_setup(1);  // 1 puts it in idle mode, 0xffff never triggers, 2-0xfffe produces pulses.
}

// Macro to Fire a one-shot pulse. Use the most recently set width.
#define OSP_FIRE() (TCNT1 = OCR1B - 1)

// Macro to Test there is currently a pulse still in progress
#define OSP_INPROGRESS() (TCNT1>0)

// Macro to Fire a one-shot pulse with the specififed width.
// Order of operations in calculating m must avoid overflow of the unint16_t.
// TCNT2 starts one count lower than the match value because the chip will block any compare on the cycle after setting a TCNT.
#define OSP_SET_AND_FIRE(cycles) {uint16_t m=0xffff-(cycles-1); noInterrupts();OCR1B=m;TCNT1 =m-1;interrupts();}

// ##########  End of Timer1 One-shot functions
ISR(TIMER1_OVF_vect) { //When overflow...
  //  OCRA1=ICR1; // Constant off in WGM 14, COM1A1:0==0b11
  TCCR1B &= ~(0b111 << CS10) ; //turn off clock
}

//######### ADC Bit-bang for free-running capture of A0
void adc_setup_freerunning(const byte adcPin){
  // set the analog reference (high two bits of ADMUX) and select the
  // channel (low 4 bits).  this also sets ADLAR (left-adjust result)
  // to 0 (the default).
  ADMUX = bit (REFS0) | (adcPin & 0x07);

  // Set the ADC ADPSx prescaler flags to control sampling speed/accuracy
  ADCSRA &= ~(bit (ADPS0) | bit (ADPS1) | bit (ADPS2)); // clear prescaler bits

  //ADCSRA |= 0b001 << ADPS0;   //   2    5 bit,
  //ADCSRA |= 0b010 << ADPS0;   //   4    6 bit, 5.36us
  //ADCSRA |= 0b011 << ADPS0;   //   8    9 bit, 6.51us
  ADCSRA |= 0b100 << ADPS0;   //  16   10 bit, 13us
  //ADCSRA |= 0b101 << ADPS0;   //  32     10 bit, 26us
  //ADCSRA |= 0b110 << ADPS0;   //  64     10 bit, 52us
  //ADCSRA |= 0b111 << ADPS0;   // 128     10 bit, 104us

  //enable automatic conversions, start them and interrupt on finish
  //ADCSRA |= bit(ADATE) | bit (ADSC) | bit (ADIE);
    ADCSRA |= bit(ADATE) | bit (ADSC) ;

}

void setup ()
{
  Serial.begin (115200);
  //pinMode(pulsePin, OUTPUT);
  osp_setup(); // Config Mega Digital 12 for oneshot output
  adc_setup_freerunning(adcPin);

}  // end of setup

// ADC complete ISR
ISR (ADC_vect)  // Store ADC burst values
{
  if (sample >= numSamples) // watch off-by-one
  {
    ADCSRA &= ~bit(ADIE);  // end of sampling burst so stop interrupting
    return;
  }
  // Handle samples
  samples[sample++ ] = ADC;
  //if ( sample == 0){
   // OSP_SET_AND_FIRE(pulse_us * 2); //
  //}
}  // end of ADC_vect

void loop ()
{
  char c;
  char buff[80];
  unsigned long sampleDuration;
  unsigned long pulseDuration;
  // if last reading finished, process it

  // if we aren't taking a reading, start a new one

  if (Serial.available()) {
    c = Serial.read();
    switch (c) {
      case 'c': // Converting?
        Serial.print("ADCSRA: ");
        Serial.println(ADCSRA, BIN);
        break;
      case 's': // stop conversions
        ADCSRA &= ~(bit (ADSC) | bit (ADIE));
        break;
      case 'r': // restart conversions
        ADCSRA |= bit (ADSC) | bit (ADIE);
        break;
      case 'v':
        adcReading = ADC;
        Serial.print(adcReading);
        Serial.print(' ');
        Serial.print((0.5 + adcReading) * 5.0 / 1024, 4);
        Serial.println(" V");
        break;
      case 'm':
        {
          unsigned long sampleDuration = sampleEnd - pulseStart;
          unsigned long pulseDuration  = pulseEnd - pulseStart;

          Serial.print("# Pulse: ");
          Serial.print(pulseDuration);
          Serial.print("us and ");
          Serial.print(numSamples);
          Serial.println(" samples.");
          Serial.print("# Time: ");
          Serial.print(sampleDuration);
          Serial.print("us burst of ");
          Serial.print(numSamples);
          Serial.print(" samples at ");
          Serial.print(1.0 * (unsigned long)(sampleEnd - pulseStart) / numSamples);
          Serial.println("us/sample");
          sprintf(buff, " sampleEnd, pulseEnd, pulseStart %02lu : %02lu : %02lu \n", sampleEnd, pulseEnd, pulseStart);
          Serial.print(buff);
          break;
        }
      case 'p': // start pulse
        sample = 0;  // reset sample SV
        pulseStart = micros();
        OSP_SET_AND_FIRE(pulse_us * 2); // pulse outside ISR
        ADCSRA |= bit(ADIF) | bit(ADIE); // clear existing ADInterruptFlag and enable ADC Interrupts
        while(BURST); // block until burst done
        sampleEnd = micros(); // Record times
        pulseEnd = pulseStart + pulse_us;
        break;
      case 'D':
      case 'd': {// report Data
          sampleDuration = sampleEnd - pulseStart;
          for (int ii = 0 ; ii < numSamples ; ii++) {
            if (c == 'D') {
              Serial.print(ii * sampleDuration / numSamples);
              Serial.print(' ');
            }
            Serial.println(samples[ii]);
          }
        }
        break;
      case ' ':
      case '\n':
      case '\r':
        break;
      case 'h':
      case '?':
      default:
        {
          Serial.println("\nArduinoPulseADCSample.in -- Pulse A1 and read a burst of samples from A0\n"
                         "based on serial commands");
          Serial.println("# https://github.com/drf5n/foxyPulseInduction_Discrimination/tree/discrimination/ArduinoPulseADCSample\nCommands: [vcsrpdm] ?");
          Serial.println("Commands:\n"
                         "p: Pulse -- Start a pulse cycle on A1 and record data on A0\n"
                         "d,D: Data -- Dump the data from the last pulse\n"
                         "m: Metadata -- Print the length of pulse, number of samples and rate\n"
                         "v: Voltage -- Conver voltage on A0\n"
                         "c: Converting? -- show ADCSSRA register\n"
                         "h?: Help -- Print this\n"
                        );
        }
        break;
        ;;
    }
  }

  // do other stuff here

}  // end of loop

This is the output from the p,m,d commands with a jumper connecting pin 12 to A0 with the /16 prescaler:
# Pulse: 50us and 20 samples.
# Time: 276us burst of 20 samples at 13.80us/sample
 sampleEnd, pulseEnd, pulseStart 19270968 : 19270742 : 19270692
0
1020
1023
1023
1023
3
0
0
0
0
0
0
0
0
0
0
0
0
0
0

And again with the /8 prescaler.  7.2us/sample or 139Ksamples/sec for 8-9bits isn't bad:
# Pulse: 50us and 20 samples.
# Time: 144us burst of 20 samples at 7.20us/sample
 sampleEnd, pulseEnd, pulseStart 4229952 : 4229858 : 4229808
0
792
1020
1022
1022
1020
1022
1022
1022
305
3
0
0
0
0
0
0
0
0
0

ArduinoPulseADCSample.in -- Pulse A1 and read a burst of samples from A0
based on serial commands
# https://github.com/drf5n/foxyPulseInduction_Discrimination/tree/discrimination/ArduinoPulseADCSample
Commands: [vcsrpdm] ?
Commands:
p: Pulse -- Start a pulse cycle on A1 and record data on A0
d,D: Data -- Dump the data from the last pulse
m: Metadata -- Print the length of pulse, number of samples and rate
v: Voltage -- Conver voltage on A0
c: Converting? -- show ADCSRA register
h?: Help -- Print this

Here's an R-C pulse-decay trace on the Serial Plotter with a 22K resistor across A0&12 and a 22uF capacitor from GND to A0.

Re “I left free-running automatic ADC enabled and switched the data recording on and off.”: I think you could do that by toggling just ADIE, without touching ADSC. Maybe clear the interrupt flag when setting ADIE, to avoid getting an interrupt from the last conversion of the previous burst.

@EdgarBonet -- With the ADIF=1 trick, ADCSRA |= bit(ADIF) | bit(ADIE) would clear any pending interrupt and enable future interrupts.  Sounds good.  I could then use the ADCSRA & bit(ADIE) instead of burst as my "sampling" state variable and save a test. I've been tweaking things to get down to the 13us/sample threshold that I can get for the ADPS2:0=0b100 /16 1MKz speed that has full 10bit accuracy, but I haven't trimmed the ISR down enough for the /8 clock. I like the pulse control in the ISR for the sync in my use case, but it's sloppy. Maybe pulse on sample vs micros() state var?

... The pulse length control is sloppy because the pulse is started out of sync with the sampling, and finishes in sync with the sampling.  I like the end synchronization with the samples for my particular application, but it would be nicer to configure a timer as a one-shot and trigger it in the ISR when the sample == 0, then you could get higher resolution pulse lengths with both the start and end of the pulse synced with the sampling.   Maybe it could reach 6.5us/sample with 8-9 bit resolution.


text:
ESP32 how to preserve RTC time during brownout
I want to use the ESP32 built-in RTC clock.
In my situation, my ESP32 will not have access to an NTP server
I do not want to use external RTC modules
ESP32 provides a pin VDD_RTC will powers the RTC domain exclusively
My problem would be solved if I attach a coin cell to this pin.
In this case, in the event of a brownout, the VDD_RTC will be powered and RTC clock preserved.
But, all dev kits I have seen seem to have VDD_CPU, VDD_DSIO and VDD_RTC connected together
So, if I would use a battery or some sort of small ups to power my ESP32 during brownout, it will be depleted by the use of GPIOs and CPU and other functions.
Solution would be here to detect brownout and force ESP32 to go to deep sleep, and then wake it up after brownout. But this would require an external source attached to a ESP32 pin to trigger deep sleep, and I don't see any pin to trigger it
Maybe I could have a circuit that would give me a signal when there is a brownout. I could attach this signal to a GPIO pin and trigger an interrupt that makes ESP32 go into deep sleep
But it seems too much for something that I am sure is super basic and should be implemented already somehow in a more convenient way
Could anyone share with me any experiences of how to preserve RTC using minimum external circuitry?

have you looked at the ESP32 datasheet? ... or ESP32 application note ... one of then may have a recommended circuit schematic

I did and I couldn't find anything interesting

You don't need to do anything special to detect Brownouts. ESP32 itself detects them, and would reset the chip automatically. The reset reason would then indicate a brownout (don't remember the exact name). So you only need to check for the reset reason at the start of your code, whether it is normal powerup, or brownout. The esp won't boot up until the brownout is over, so you don't even need to check when the brownout condition starts nor when it stops.
Moreover, in general (irrespective of brownouts) you don't need any external pins to set the esp32 to sleep, nor do you need them to wake it up. You simply call:
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
esp_deep_sleep_start();

The first line tells the esp how long to sleep. The second one initiates deep sleep. The esp32 (unlike the esp8266), will automatically wake itself back up. If a brownout happens while it is asleep, it will boot up again once the brownout is over, but the wake-up reason would be different depending on the case.
The default voltage that triggers the brownout condition is I think 2.8V. This is only configurable in esp-idf, not Arduino. But you don't have to worry about it. Above 2.8V the esp32 continues to keep time correctly. Below 2.8V, it halts, then wakes up once it rises above 2.8V. However, if you don't use an external RTC, and don't use a stable power source, there is no way to keep track of time after the brownout. You can't know how long the brownout was. There is no way to do this. The only option is then to find the pin that supplies the RTC alone, sever it, and wire it to a separate battery. This requires alot of SMD skills.

I think built-in brownout detector is not good for me because it resets the chip. I need it to go to sleep in order to keep the internal RTC running.

there was a discussion on this blog a while ago -- https://esp32.com/viewtopic.php?t=1558


text:
PID cooler temperature control
Hello Hello I am making a controller of a small cooler (dry ice) PID but Im not sure if I am using the indicated mosfet
Im trying with a NPN 222a
and my second option is IRFZ44
Which would be the best option?

#include <DallasTemperature.h>
#include <OneWire.h>

#define PWM 13   //-------------AquÃ definimos las constantes que se van a utilizar en el programa
const int analogin_potA = A0;

//Definiciones componentes
#define heater1 5   //TIP34c
#define sensor1 A2  //TMP36

// Variables globales
byte man_byte=0;
float Kc=1; //---- Constante proporcional del PID
float Taui=100000; //----- Constante integral del PID
float Taud=0; //----- Constante derivativa del PID
float T=0.5;  //------ Periodo de muestreo de la variable de proceso   // Ts
float Mk=0; //----ManipulaciÃ³n del PID actual
float Mk1=0; //----- ManipulaciÃ³n del PID del tiempo de muestreo anterior

float E=0; //----- Error actual
float E1=0;  //----- Error anterior
float E2=0; //------- Eerror 2 veces atrÃ¡s del tiempo de muestreo actual
float Ref_Temp=5; //-------- Referencia de la temperatura (Â°C)
float Temp=0; //----- Variable de proceso (temperatura)
//---------------- Constantes del PID digital ---------------
float BC1=0;
float BC2=0;
float BC3=0;
//----------------

void setup()   {
%Serial.begin(9600);
%Serial.write(Temp);
pinMode(analogin_potA, INPUT);
BC1=Kc*(1+(T/Taui)+(Taud/T));
BC2=Kc*(-1-(2*Taud/T));
BC3=Kc*Taud/T;
}

void loop() {   // Este es la funciÃ³n que se ejecuta cÃclicamente dentro del Arduino
Temp = analogRead(analogin_potA);
// AquÃ va la calibraciÃ³n del sensor para convertir los volts leidos en Â°C

//
E = Ref_Temp - Temp;

Mk=Mk1+BC1*E+BC2*E1+BC3*E2; // Esta es la ecuaciÃ³n del PID que calcula la manipulaciÃ³n actual (Mk)

// AquÃ estamos limitando el valor mÃ¡ximo y mÃnimo de la manipulaciÃ³n a 0-255
if (Mk > 255){
Mk=255;}
if (Mk < 0){
Mk=0;}
man_byte=Mk;

analogWrite(PWM, man_byte); //AquÃ mandamos la manipulaciÃ³n actual al pin generador de PWM (pin 5 del arduino)

//AquÃ recorremos la manipulaciÃ³n actual a la manipulaciÃ³n anterior, el error actual al error anterior y el error 2 veces anterior al error anterior.
Mk1=Mk;
E2=E1;
E1=E;

//AquÃ irÃa la comunicaci+on serial con la computadora para desplegar el valor de la temperatura y leer el valor de la referencia.
Serial.println("Temperatura_1");
    Serial.print(Temp);
    delay(1000);
//

}

which ever one that works without overheating ... you did not say what best option actually means and your post is not about arduino

Is "NPN 222A  supposed to be a 2N2222A NPN transistor?    If so, the IRFZ44's  60A limit can handle much higher current than the 2N2222's 600mA capability.   How much current do you want to drive through your Peltier?


text:
How to use ESP-01 GPIOs for input?
I'm trying to use one of ESP-01 GPIOs as an input, however, I'm always reading 1 and nothing attached to these pins.
Basically, I'm trying to detect high voltage from another sensor like a touch sensor or infrared to do some stuff (initial state will be low, so boot won't be affected).
So what I'm supposed to do to read the actual value 0?
Here is the code I'm running:
#define PIN0 0
#define PIN2 2
#define PIN3 3 // Using RX as GPIO

void setup() {
  Serial.begin(115200,SERIAL_8N1,SERIAL_TX_ONLY);
  pinMode(PIN0, INPUT);
  pinMode(PIN2, OUTPUT);
  pinMode(PIN3, INPUT);
  digitalWrite(PIN2, HIGH);
  digitalWrite(PIN0, LOW);
  digitalWrite(PIN3, LOW);
}

void loop() {
  Serial.print("PIN0: ");  Serial.print(digitalRead(PIN0));  Serial.print("\t");
  Serial.print("PIN2: ");  Serial.print(digitalRead(PIN2));  Serial.print("\t");
  Serial.print("PINRX: ");  Serial.print(digitalRead(PIN3));  Serial.println("");

  delay(500);
}

Here is the Serial Reading:
PIN0: 1 PIN2: 1 PINRX: 1
PIN0: 1 PIN2: 1 PINRX: 1
PIN0: 1 PIN2: 1 PINRX: 1
PIN0: 1 PIN2: 1 PINRX: 1

esp-01S has pull-up on io 0

You are writing 0 to an input pin. From the Arduino reference:
"If the pin is configured as an INPUT, digitalWrite() will enable (HIGH) or disable (LOW) the internal pullup on the input pin. It is recommended to set the pinMode() to INPUT_PULLUP to enable the internal pull-up resistor."
Also, when you leave an input pin floating, ie. don't connect anything to it, and also don't enable (or explicitly disable) the internal pull-up or connect an external pull-up, the input pin can show 1, or it could show 0.
TL;DR: You shouldn't leave the input pins floating; floating pins are susceptible to electrical noise and can show anything or even fluctuate. If you want them to show 0 when nothing is connected, add an external pull-down resistor.


text:
How to make better looking webpages on an Arduino webserver?
I have a Teensy 4.1 with ethernet, but I have other networked MCUs like a D1 mini, various ESP8266s and Arduino ethernet shields.
My question is: how I can make better looking web pages on these devices, where having a filesystem is limited by memory, or which lack a filesystem.
Specifically, I would like to add SVG images; I'm interested in how to make things like background images. I understand HTML/CSS, and I can code in C, get my data, whatever, but I want to make the page look good too.
Here's an example of the issue as it relates to HTML being rendered; here is an HTML page:
<!DOCTYPE html>

Cool, well to write that in something an Arduino can render, you use print statements; you might write:
// listen for incoming clients
// forgoing all of server setup
EthernetClient client = server.available();
client.println("<!DOCTYPE html>");

This won't work without a filesystem, or won't work as is.
Then, I tried inline SVG:
// listen for incoming clients
// forgoing all of server setup
EthernetClient client = server.available();
client.println("<!DOCTYPE html>");

This works, sometimes, but seems to have limitations as well.
I'm just wondering how I can make great looking webpages with stylesheets on an Arduino, only using print statements, or not requiring a filesystem.

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

I can put files in there? storage I think isnt the issue. its that example.txt is a file pointer, not a datastream, or string literal that html / css is looking for. but that does give me an idea

Do a web search for “C++ raw string literal”. It is a convenient syntax for writing big, multi-line strings, that you can output on a single client.println().

https://stackoverflow.com/questions/12930978/array-of-strings-char-array-in-c-arduino-how-do-i-accomplish-it

oh, thanks, but html/css inline function havent worked for me yet doing that. I wrote a script a few days ago to handle that type of operation. its mainly that the url() in css seems to have limits on what it can do for images. I was using svg anyway, but if I werent.. wait, I think I read about this in PoC||GTFO

I'm not sure how it works on the teensy, but on the ESP chips you should use SPIFFS to store your website files and just serve them in your code (no string synthesis for serving the client html in code). You can even save images there, though high res images can fill the storage very fast. Also: When you want to design good looking websites have a look at Bootstrap. It provides many useful tools that already look good (buttons, tab bars, forms,...). If the client doesn't have internet connection, then you can even download bootstrap onto the ESP. Isn't that big.

yeah, spiffs seem like a neat feature, but I haven't seen anything like that for anything other than esp8266, and esp32 chips. maybe its not too hard to port, but I didn't look into it further.

Your method of embedding SVG seems unnecessarily complicated to me. You don't need to give a URL of anything. Below is valid for putting SVG onto a web page:
<!DOCTYPE html>

  <meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
  <title>Test</title>

  <svg width="500" height="500">
    <rect x="5" y="5" width="450" height="450" fill="lightblue" stroke="black"></rect>
  </svg>

Hello, world

The "position:absolute" and the z-index styles put the SVG in a fixed position on the page (like a background image) and underneath anything else you might put there.

well, I still want to know more about writing great looking webpages on ardunio network devices.
I got my immediate issue sorted for now.
html/css seems to have some issues I dont quite understand as they relate to print statements, and Im pretty sure the url attribute is what is getting me.
I found this great github project that encodes svg for css inline functions.
https://yoksel.github.io/url-encoder/

I set up a basic web server example to simplify the code I was looking at.
its weird, on html pages I have put full style sheets on one line and never had a problem. here, it wouldn't work until I broke the style sheet into multiple lines (even with the url encoded svg).
Here is my simpler example for a page with a background image:
#include <SPI.h>
#include <NativeEthernet.h>
void  pageWrite(EthernetClient client);
void listenClient(EthernetClient client);
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(10, 1, 0, 177);
EthernetServer server(80);
void setup() {

  delay(5000);  //you want this delay. reason: tl;dr
  Serial.begin(9600);
  Ethernet.begin(mac, ip);

if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  }
  // start the server
  server.begin();
  delay(100);
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
} //end setup

void loop() {
      EthernetClient client = server.available();
listenClient(client);
}  //end loop
void listenClient(EthernetClient client){

   if (client) {
    boolean currentLineIsBlank = true;
    while (client.connected()) {
       if (client.available()) {
          char c = client.read();
       // Serial.write(c);   //tells about the client connection
        if (c == '\n' && currentLineIsBlank) {
          pageWrite(client);
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }//end avail
    } //end conect
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
  } //end client
}//end listenClient()
void  pageWrite(EthernetClient client){
client.println("<!DOCTYPE html>");
    }

You can serve a whole webapp from spiffs. The ESP doesn't care if it's a pretty (e.g. javascript-based) webapp or a plain html file. The webapp can then communicate with the ESP via a socket connection. You wouldn't even have much webapp-related code in your sketch (beside of serving the webapp file). I personally would forget about this string synthesis in RAM completely.

very interesting, I will check that out.

As I understand what you want to send is basically a big string(s) stored in memory. You can quite easily store it  it in external memory. You can use FRAM which is non volatile with 32K x 8 modules available for less then $5.00. They will run (Read / Write) at I2C or SPI speeds, no delays for writing or reading. There are other memory types that will also do the job but this is simple and inexpensive.
I am currently doing that with a project I am working on.  It is using an Arduino Nano with about 20K of messages and several of application / program data that I store. Flash will not contain the messages and the program, not enough room. The program data is created via sensors and a rotary switch. I load the data into the FRAM sometimes in sections depending on size with my loading code. I then go to my application code which retrieves the messages from the FRAM and displays them on the LCD and terminal.
There is a pointer table in a specific location in FRAM that is pointing to each message address, size etc. This allows messages and other data to change without changing the main code. The FRAM in my case is a plug in module. This approach although a bit convoluted works nicely and you do not have to have a file structure. You can if you want. I do not know if this will work for you but it does for me.

Gonna answer my own question again lol.
I looked at spiffs, but it seemed to just be an esp thing.
anyhow, I realized that <!DOCTYPE html>
probably wasn't the only doctype there is, and that svg would probably render just fine without html or css. which is true! I used <!DOCTYPE svg> and got rid of html and css, which means I didn't need to use some fancy inline css encoding, and could instead make much simpler println() statements, and still generate an accessible "webpage" written in only svg.
I could probably clean up the svg too, I drew it in inkscape, which generates overly complicated svg data.
But the project works now.. in a basic sort of way anyway.
/*
An IoT Etch-A-Sketch
uses 2 rotory encoders to generate x,y data points
in a svg poly line.

*/
#include <SPI.h>
#include <NativeEthernet.h>
#include <SD.h>
File dataFile;

byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};

IPAddress ip(10, 1, 0, 177);
EthernetServer server(80);
//Function defs
void rotors();
void rotorA(EthernetClient client);
void rotorB(EthernetClient client);
void resetImg();  //erase datalog.txt
void Abuton();
void Bbuton();
void listenClient(EthernetClient client);
void pageWrite(EthernetClient client);
void polyLineBegin(EthernetClient client);
void startPage(EthernetClient client);
void endPage(EthernetClient client);

//int potX = A0;
//int potY = A1;

int sensorValX = 0;
int sensorValY = 0;

int oldX = 0;
int oldY = 0;

/**Rotor Vars**/
// Rotary Encoder Input defintions
#define CLKA 2
#define DTA 3
#define SWA 4

#define CLKB 5
#define DTB 6
#define SWB 7

int Acounter = 0;
int Bcounter = 0;

int AcurrentStateCLK;
int BcurrentStateCLK;

int AlastStateCLK;
int BlastStateCLK;

unsigned long AlastButtonPress = 0; //butons on rotory encoders
unsigned long BlastButtonPress = 0;

void setup() {

  delay(10000);  //you want this delay. reason: tl;dr
  /** Set encoder pins as inputs **/
  pinMode(CLKA,INPUT);
  pinMode(DTA,INPUT);
  pinMode(SWA, INPUT_PULLUP);
  pinMode(CLKB,INPUT);
  pinMode(DTB,INPUT);
  pinMode(SWB, INPUT_PULLUP);

  // Read the initial state of CLK
  AlastStateCLK = digitalRead(CLKA);
  BlastStateCLK = digitalRead(CLKB);
  /***End Rotary Encoder vars****/

  Serial.begin(9600);

  Ethernet.begin(mac, ip);

if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  }

  // start the server
  server.begin();
  delay(100);
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
  Serial.print("Initializing SD card...");

  if (!SD.begin(BUILTIN_SDCARD)) {
    Serial.println("SD Card init failed!");
    while (1);
    }
/****SD CARD and Ethernet intialized*****/
//if data file (on SD Card) Doesn't exist, create it.
//if data file (on SD Card) does exist errase it and create a new one
  if (SD.exists("datalog.txt")) {
     Serial.println("datalog.txt exists: \n Removing it.");
     while(SD.remove("datalog.txt")!=1){
       Serial.println("Deleeting old file data");
       if (SD.remove("datalog.txt")==1){
          Serial.println ("old dataFile removed");
       }
     }
  } else {
    Serial.println("datalog.txt doesn't exist.");
         }

  // open a new file and immediately close it:
  Serial.println("Creating datalog.txt...");
  dataFile = SD.open("datalog.txt", FILE_WRITE);
  dataFile.close();

  // Check to see if the file exists:
  if (SD.exists("datalog.txt")) {
    Serial.println("datalog.txt exists.");
  } else {
    Serial.println("datalog.txt wasn't created.");
         }
} //end setup

void loop() {
 // listen for incoming clients
  EthernetClient client = server.available();
rotors();
listenClient(client);
}  //end loop
void listenClient(EthernetClient client){

   if (client) {
    boolean currentLineIsBlank = true;
    while (client.connected()) {
       if (client.available()) {
          char c = client.read();
       // Serial.write(c);   //tells about the client connection
        if (c == '\n' && currentLineIsBlank) {
          pageWrite(client);
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }//end avail
    } //end conect
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
  } //end client
  }//end listener()

void pageWrite(EthernetClient client){
          startPage(client);
          polyLineBegin(client);
          endPage(client);
  }
void startPage(EthernetClient client){
     // doctype svg no need for html
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");  // the connection will be closed after completion of the response
          client.println("Refresh: 1");  // refresh the page automatically every 5 sec
          client.println();
          client.println("<!DOCTYPE svg>");
          client.println("<svg   xmlns='http://www.w3.org/2000/svg'  viewBox='0 0 227.35277 156.29323' height='6.1532764in' width='8.9508963in'><path  style='fill:#ff0000; stroke:#ff0000; stroke-width:1.32300019;stroke-miterlimit:4; stroke-dasharray:none; stroke-opacity:1' d='m 12.000819,0.66145838 c -6.2819637,0 -11.33936062,5.05739692 -11.33936062,11.33936062 V 144.29249 c 0,6.28197 5.05739692,11.33936 11.33936062,11.33936 H 215.35224 c 6.28197,0 11.33885,-5.05739 11.33885,-11.33936 V 12.000819 c 0,-6.2819637 -5.05688,-11.33936062 -11.33885,-11.33936062 z M 18.932696,12.696383 H 205.5854 c 5.02557,0 9.07128,4.04571 9.07128,9.071282 v 77.03923 c 0,5.025575 -4.04571,9.071285 -9.07128,9.071285 H 18.932696 c -5.025572,0 -9.0712819,-4.04571 -9.0712819,-9.071285 v -77.03923 c 0,-5.025572 4.0457099,-9.071282 9.0712819,-9.071282 z' /><ellipse style='fill:#ffffff;fill-opacity:1; stroke:#ff0000; stroke-width:1.32300007; stroke-miterlimit:4; stroke-dasharray:none; stroke-opacity:1' cx='21.16666'  cy='130.59085'  rx='10.583334' ry='9.0714283' /><ellipse  style='fill:#ffffff; fill-opacity:1; stroke:#ff0000; stroke-width:1.32300007; stroke-miterlimit:4; stroke-dasharray:none;stroke-opacity:1' cx='200.62982'   cy='131.57361' rx='10.583334' ry='9.0714283'/>");
          client.println("\n<polyline points='15,15");
   }
 void endPage(EthernetClient client){
  client.print("' \nfill='none' stroke='#ff0000'/></svg>");
   }
void polyLineBegin(EthernetClient client){
//read data points from SD card
    File dataFile = SD.open("datalog.txt");
  // if the file is available, read it:
  if (dataFile) {
    while (dataFile.available()) {
      //Serial.write(dataFile.read());
      client.write(dataFile.read());
    }
    dataFile.close();
  }
}

int rotorA(){ //X coords
  AcurrentStateCLK = digitalRead(CLKA);
  if (AcurrentStateCLK != AlastStateCLK  && AcurrentStateCLK == 1){
     if (digitalRead(DTA) != AcurrentStateCLK) {
      Acounter --;
      }else{
       Acounter ++;
       }
     }
// Remember last CLK state
  AlastStateCLK = AcurrentStateCLK;
Abuton(); //errase the data file if A button pressed.
//X limits
if(Acounter<=15){
  Acounter=15;
  }
if(Acounter>=215){
  Acounter=215;
  }
return Acounter;
  }//endA rotor

int rotorB(){ //Y coords
  BcurrentStateCLK = digitalRead(CLKB);
  if (BcurrentStateCLK != BlastStateCLK  && BcurrentStateCLK == 1){
    if (digitalRead(DTB) != BcurrentStateCLK) {
       Bcounter --;
       }else{
        Bcounter ++;
     }
    //Serial.println(Bcounter);
  }
  BlastStateCLK = BcurrentStateCLK;
Bbuton();
//Y limits
if(Bcounter<=15){
  Bcounter=15;
  }
if(Bcounter>=210){
  Bcounter=210;
  }
  return Bcounter;
  }//EndB rotor

void rotors(){
//read rotors and write x,y points to datalog.txt
 sensorValX=rotorA();
 sensorValY=rotorB();
String dataString = "";

if(sensorValX!=oldX || sensorValY!=oldY){
   dataString += ",";
   dataString += String(sensorValX);
   dataString += ", ";
   dataString += String(sensorValY);

   Serial.println(dataString);

   dataFile = SD.open("datalog.txt", FILE_WRITE);
    // if the file is available, write to it:
   if (dataFile) {
      dataFile.print(dataString);
      dataFile.close();
      //clear dataString
      dataString="";
      }else{
    // if the file isn't open, pop up an error:
    Serial.println("error opening datalog.txt");
  }
  dataFile.close();
  }else{
  ;
  }

 oldX=sensorValX;
 oldY=sensorValY;

}//end rotors
void resetImg(){
  //clear datapoints by errasing datafile.
  if (SD.exists("datalog.txt")) {
     Serial.println("Deleting data.");
     while(SD.remove("datalog.txt")!=1){
       Serial.println("Deleeting old file data");
       if (SD.remove("datalog.txt")==1){
          Serial.println ("old dataFile removed");
       }
     }
  } else {
    Serial.println("datalog.txt doesn't exist.");
         }

  // open a new file and immediately close it:
  Serial.println("Creating datalog.txt...");
  dataFile = SD.open("datalog.txt", FILE_WRITE);
  dataFile.close();

  // Check to see if the file exists:
  if (SD.exists("datalog.txt")) {
    Serial.println("New datalog.txt created.");
  } else {
    Serial.println("datalog.txt wasn't created.");
         }

  }//end resetImg

void Abuton(){ //X buton
    int AbtnState = digitalRead(SWA);
  //If we detect LOW signal, button is pressed
if (AbtnState == LOW) {
    if (millis() - AlastButtonPress > 500) {
      Serial.println("Resting image!");
      resetImg();
    }
  AlastButtonPress = millis();
  }
  } //end Abuton

void Bbuton(){ //Y buton
int BbtnState = digitalRead(SWB);
    if (BbtnState == LOW) {
    //if 50ms have passed since last LOW pulse, it means that the
    //button has been pressed, released and pressed again
    if (millis() - BlastButtonPress > 50) {
      Serial.println("Button B pressed!");
    }
    BlastButtonPress = millis();
  }
}

Note that, if you send SVG, you don't need the DOCTYPE line, but you should fix the Content-Type: it should be "image/svg+xml", not "text/html".

Here's an alternative way of doing things I like to use:
What I like to do, when working with Arduinos with a decent amount of memory like the SAMD21-based ones, is create a fully self-contained webpage, that is, a webpage that has all HTML, CSS and Javascript in the same file, and all bitmap and SVG images in-lined in that same file. In short, a webpage file that is completely self-contained.
I then gzip that file (which compresses it a lot), and then base64 encode the gzipped file. The base64-encoded page is then copy/pasted into the code / memory as a const char*.
When the page needs to be served, I base64-decode it, and then serve the gzipped version, which all browsers accept if you put Content-Encoding: gzip in the header.
I put an elaborate example on Github, maybe you can get some inspiration from that. The webpage in the example is 26.8 kB in size, and the base64-encoded, gzipped webpage string as put into the code comes in at a little under 7 kB.

This is an interesting approach, but I do not see the usefulness in using base64 encoding. It makes your document consume 33% more memory, then you allocate the original size on the stack in order to decode it (at which point it occupies 233% of its size), and you need the extra code for decoding. It would be more efficient to store the gzipped page unencoded, as an array of bytes (not a C string).

@EdgarBonet: I know, but using base64 encoding makes it easier to copy/paste the contents of a file into the code without breaking it because of the control characters etc. in the gzip-ed file. I had enough memory, so I didn't go the more efficient way of escaping the problematic characters in the gzip output and use that. I will admit to some laziness here.


text:
Arduino uno spi sck not working
I am trying to verify sck output on my arduino uno. I don't have oscilloscope so I loopbacked miso to sck and tried Executing int rx0=SPI.transfer(5) while printing this using Serial.printrx0) it is giving 255.Whether this is expected output?

I'd expect you'll get all bit with the same value. You can try other SPI_MODES and you probably get 0x00 for two of them..  However you could use loopback between MOSI a MISO (you can expect 1B delay)

Hi KIIV, THANKS for responding.. I tried all the SPI mode and I got 255 as output, means all the bit as 1 in the byte. Whether it is right result?whether I can say my sck output is normal? Thanks

You could instead send SCK to T1 (pin 5), configure Timer 1 as a counter, and use it to count the clock pulses.

As suggested by KIIV and myself, you can test the SPI port by:

connecting MOSI to MISO and checking if you receive what you send
connecting SCK to the timer input T1 and counting the clock pulses.

Below is a sketch that performs both tests:
/*
 * Test the SPI port.
 *
 * Connect:
 *   MOSI (11) to MISO (12)
 *   SCK (13) to T1 (5)
 */

void setup() {
    Serial.begin(9600);

    // Configure SPI port.
    DDRB |= _BV(PB2)   // SS (digital 10) as output
          | _BV(PB3)   // MOSI (digital 11) as output
          | _BV(PB5);  // SCK (digital 13) as output
    SPCR = _BV(SPE)    // enable port
         | _BV(MSTR);  // master mode

    // Configure Timer 1.
    TCCR1A = 0;          // normal mode
    TCCR1B = _BV(CS10)   // count rising edges of T1 = digital 3
           | _BV(CS11)   // ditto
           | _BV(CS12);  // ditto
}

void loop() {
    TCNT1 = 0;  // clear timer
    uint8_t data = random(256);
    Serial.print(data);
    Serial.print(" -> ");
    SPDR = data;  // send
    delay(1);
    if (bit_is_set(SPSR, SPIF)) {  // transfer complete?
        Serial.println(SPDR);
    } else {
        Serial.println("nothing received");
    }
    Serial.print("    clock pulses: ");
    Serial.println(TCNT1);
    delay(1000);
}

It should print:
167 -> 167
    clock pulses: 8
241 -> 241
    clock pulses: 8
217 -> 217
    clock pulses: 8
[...]


text:
Azure IoT times out while trying to send a message from an ESP32
I am looking for a working example of an ESP32 sending telemetry data to Azure IoT hub. I find nothing working around the internet: below is the code I am trying to make it working.
As you can see in the logs, after a successful connection to the WiFi, followed by a successful connection to IoT Hub, the message has been accepted by the drive, but it is never sent successfully: Sound kinda timeout.
I posted the full Arduino SW for you to try.
[UPDATE]
You need to install the ESP32MQQTClient lib from Microsoft that you'll find right there: https://platformio.org/lib/show/5462/ESP32%20Azure%20IoT%20Arduino
Bottom note: IoT Hub is fully configured and working, and device is provisioned and the connection string is OK.
And the logs are as follows:
11:36:50.573 -> mode:DIO, clock div:1
11:36:50.573 -> load:0x3fff0018,len:4
11:36:50.573 -> load:0x3fff001c,len:1216
11:36:50.609 -> ho 0 tail 12 room 4
11:36:50.609 -> load:0x40078000,len:10944
11:36:50.609 -> load:0x40080400,len:6388
11:36:50.609 -> entry 0x400806b4
11:36:50.881 -> ============ Starting connecting WiFi.
11:36:51.513 -> ......
11:36:54.011 -> ============ WiFi connected
11:36:54.011 -> IP address:
11:36:54.011 -> 192.168.1.20
11:36:54.011 -> Info: Initializing SNTP
11:36:54.999 -> Info: SNTP initialization complete
11:36:54.999 -> Info: IoT Hub SDK for C, version 1.1.23
11:36:58.050 -> Info: >>>Connection status: connected

11:36:58.050 -> ============ start sending events.
11:36:58.083 -> Info: >>>IoTHubClient_LL_SendEventAsync accepted message for transmission to IoT Hub.

11:37:08.066 -> Error: Time:Fri Nov 19 10:37:08 2021 File:/Users/stephanedeluca/Library/Arduino15/packages/esp32/hardware/esp32/1.0.6/libraries/AzureIoT/src/Esp32MQTTClient.cpp Func:SendEventOnce Line:316 Waiting for send confirmation, time is up 10006

11:37:08.099 -> Info: >>>Re-connect.

11:37:08.099 -> Error: Time:Fri Nov 19 10:37:08 2021 File:/Users/stephanedeluca/Library/Arduino15/packages/esp32/hardware/esp32/1.0.6/libraries/AzureIoT/src/az_iot/c-utility/pal/src/tlsio_openssl_compact.c Func:tlsio_openssl_destroy Line:213 tlsio_openssl_destroy called while not in TLSIO_STATE_CLOSED.

11:37:08.136 -> Info: >>>Confirmation[0] received for message tracking id = 0 with result = IOTHUB_CLIENT_CONFIRMATION_BECAUSE_DESTROY

11:37:08.136 -> Info: Initializing SNTP

11:37:09.109 -> Info: SNTP initialization complete

11:37:09.109 -> Info: IoT Hub SDK for C, version 1.1.23

11:37:09.470 -> Info: >>>IoTHubClient_LL_SendEventAsync accepted message for transmission to IoT Hub.

11:37:10.911 -> Info: >>>Connection status: connected

11:37:18.134 -> Error: Time:Fri Nov 19 10:37:18 2021 File:/Users/stephanedeluca/Library/Arduino15/packages/esp32/hardware/esp32/1.0.6/libraries/AzureIoT/src/Esp32MQTTClient.cpp Func:SendEventOnce Line:316 Waiting for send confirmation, time is up 10049

11:37:18.134 -> xxxxxxxxxxxx Failure sendind data: {"batteries":{"0":{"current": 1234.5}}}...

#include <WiFi.h>
#include "Esp32MQTTClient.h"

// Please input the SSID and password of WiFi
const char* ssid     = "XXX";
const char* password = "XXX";

/*String containing Hostname, Device Id & Device Key in the format:                         */
/*  "HostName=<host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>"                */
/*  "HostName=<host_name>;DeviceId=<device_id>;SharedAccessSignature=<device_sas_token>"    */
static const char* connectionString = "XXX";
static bool hasIoTHub = false;

void setup() {
  Serial.begin(115200);
  Serial.println("============ Starting connecting WiFi.");
  delay(10);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\n============ WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  if (!Esp32MQTTClient_Init((const uint8_t*)connectionString))
  {
    hasIoTHub = false;
    Serial.println("============ Initializing IoT hub failed.");
    return;
  }
  hasIoTHub = true;
}

void loop() {
  Serial.println("============ start sending events.");
  if (hasIoTHub)
  {
    char buff[128];

    // replace the following line with your data sent to Azure IoTHub
    snprintf(buff, 128, "{\"batteries\":{\"0\":{\"current\": 1234.5}}}");

    if (Esp32MQTTClient_SendEvent(buff))
    {
      Serial.println("============ Sending data succeeded");
    }
    else
    {
      Serial.printf ("xxxxxxxxxxxx Failure sendind data: %s...", buff); Serial.println();
    }
    delay(5000);
  }
}

Could you add code from the library file that is generating the error? It might help us understanding where the error is.

@krystof18 Sure, here is the Microsoft Esp32MQTTClient repository https://platformio.org/lib/show/5462/ESP32%20Azure%20IoT%20Arduino

The problem is probably in IoTHubClient_LL_SendEventAsync function, but I can't find where it is, it is there somewhere, but I don't have time to crawl thru all files, If you find the file where it is, it will be really helpfull.

@krystof18 Ok. My colleague tells you in a few minutes.

@krystof18 The function is at line #1006 in file https://github.com/VSChina/ESP32_AzureIoT_Arduino/blob/master/src/az_iot/iothub_client/src/iothub_client_ll.c


text:
Switching fan on with transistor, fan running very slowly
I want to control a fan with an arduino from 0 rpm to full rpm. Using a (modified) pwm signal from the arduino I can control the speed w/ the pwm signal, but it cannot go all the way to 0 rpm.
So I decided to add a transistor as a switch using following schematic.

The fan is a Snowman F120, I used BC337 as a transistor (800mA) and a resistor of 2.2 kOhm, for controller I use pin 6 on an arduino nano and set it high/low. Arduino and the fan are both run from the 12v power supply. I removed the pwm signal to just have it full on or off for testing purposes.
I was hoping to use the transistor as an on/off switch and when on just send the pwm signal as that was working already.
The fan can now be turned off/on with the arduino but it spins super slow, say 10% of full pwr. Can someone explain why this is? Is there a better way to control this?
Edit: I did try to remove the resistor completely and the fan still moves only slowly
Edit: it is a 4 wire fan, but it cannot go all the way to 0 with pwm. That's why I want the 'switch'
I lowered the resistor to 120 ohm, and switched gpio pin, no effect, if I wait long enough the transistor gets hot
Edit: I connected the transitor to the 5V of the Arduino instead of the Digital out (high) and low and behold fan works well (resistor still in between, both 120 and 2.2kOhm tested, both situations work). I guess the digital output cannot provide enough current?
**
Solution:

Used IRLZ34N mosfet with a 120Ohm as gate resistor
and a 100 kOhm as pull down resistor to GND as otherwise the mosfet would always be open
**

Is that a 4-wire fan?

With a 2.2K resistor you're massively limiting the current that can flow through the transistor.
I haven't looked up the specs on that transistor, but taking typical values for Vbe (0.6V) and Hfe (100) we can calculate:
Ibe = (5V - 0.6V) / 2200 ohm = 0.002A

Ice = Ibe x Hfe = 0.002 x 100 = 0.2A

So even though your transistor is capable of 800mA you're actually only allowing 200mA maximum.
Add to that the voltage drop of the transistor and you have a recipe for a slow fan.
Really you would be better off using an N-channel MOSFET for this job since it is controlled by the voltage at the gate, not the current flowing through it. Also in saturation mode they are more like a very low value resistor rather than a couple of diodes.
Also if your fan is a 4-wire fan (as the ones I have found on Google looking for that model are) then you don't even want a transistor: one of the pins of the fan is a PWM input which you can connect (along with fan ground) direct to the Arduino (it basically includes the transistor internal to the fan) for speed control.

The BC337 has relatively high DC gain. 4-pin fans often can not be dimmed-to-off with PWM, I guess that's why the OP wants to use the transistor.

@SimSon Every 4 pin fan I've ever used has stopped at 0% duty cycle...  That's how you achieve silent computing.

I did try to change the resitor to a low value 120 Ohm, but that did not change the outcome.
it is a 4wire fan, but it does not stop at 0% duty cycle. I was surprised too but apparently it's not that uncommen. Instead of buying new fans I decided I would add a transistor as a switch

I'm fine to switch to a mosfet, but don't have any laying around. Do you have a suggestion which one to use? Could I use it as a drop-in replacement in the same circuit?

This guy perhaps, IRLZ34N?
https://eu.mouser.com/ProductDetail/Infineon/IRLZ34N?qs=sGAEpiMZZMua%252Bgb89%252BTvM2aBJqYrAlCZ6Q%252BoLUS32zE=

That one would work fine.

Type A fans as specified by Intel do not stop at 0% duty cycle, only Type B & C do...

I ordered a couple, will be about a week until I can test.

I have used the BC337 to switch small loads like fans, so I know this works in general. As Majenko explained, 2.2kOhm base resistance is a bit high, though.
"I did try to remove the resistor completely and the fan still moves only slowly" - if you controlled the transistor without base resistor, chances are that the GPIO got damaged, try another GPIO with 500-1000 Ohm.
As a rule of thumb: If the transistor gets warm when switching a small load, something is wrong. If there's a reasonable voltage drop between emitter and collector, reduce the base resistance if possible.
Another thing is that you should not low-side-switch a 4-pin fan if you want to control it with its PWM input at the same time. In case the ground path is disconnected, the entire fan's circuit is at supply voltage level: Arduino will see 12V at its pins. Use a high-side switch instead
Edit: did you actually make sure that the fan had 100% duty cycle at the PWM input when the transistor was on?

the transistor did get hot after a some time say 20-30s. I also lowered the resistor to 120 Ohm with no effect, still gets hot. Then I changed from the Digital out to just the 5V and tested with both resistors, both seem to make the fan go full speed with the pwm disconnected. Then I connected the pwm in the same config and it could be controlled. So the digital out seems to be the issue, I tried to use 3 different pins 6, 7, and 8. All seem to produce the same issue.

@user1908460 it's also possible that the transistor is broken. The base resistor ist quite critical: if it is too low, you may exceed the base's or GPIO's current rating. If it is too high, the transistor is not operating in its saturation region, which leads to high power dissipation. Chances are that the transistor got destroyed during your previous attempts.

Good idea, I just tested two other ones with the lower resistance. Fan Also spins really slow. Connecting it to the 5V directly worked as well though.

@user1908460 set the GPIO high and measure a) voltage between GPIO and GND, b) voltage accross the base resistor, c) voltage between collector and emitter. A picture of your wiring might also help.

there is a) 0.8-0.9V over over GPIO-gnd, b) 0.24V over the resistor (120ohm), and c) 7.7V over collector-emitter.
I also tested GPIO-GND w/o any load and that was 5V.

I also did the same measurement when connecting the base resistor to 5V of the arduino instead of GPIO
a) 5V from 5V-GND
b) 4V over resistor
c) 0.1V from collector-emittor

@user1908460 the GPIO is dead. It may still work with a MOSFET but you better use a GPIO that isn't broken or replace the microcontroller. And -as I said- use a resistor between 500-1000Ohm. There's no need to load the GPIO with 36mA for your little load. That's very close to the maximum rating.

Thanks, I will order another arduino as well and test both, and find an 500-1000ohm resistor.

@user1908460 you can use 3 of the 2k2 in parallel. Btw if I would do it today, I'd also use a MOSFET like Majenko suggested.

OK, yeah since I already ordered the MOSFET, I will follow your advice. I used the transistor since I had it laying around, no need to wait for shipment....

@user1908460 you can use your 120Ohm as gate resistor for the MOSFET ;)

super thanks, yeah I would've just guessed something and probably broke something again :P


text:
Can't burn fuse bits on ATMega168 with Arduino Uno as ISP
I have an ATMega168 that I am programming via my Arduino Uno as ISP. I can burn the bootloader and transfer a hex file just fine, but I can't seem to be able to change the fuse bits. I found a lot of people having similar problems, but most still weren't resolved after many years or can't connect to their chip at all.
A weird thing I notice is that my ATMega is recognized as an 328p all the time. I know they're practically identical, but nothing works when I change settings to an 168, I always have to set it to 328p. Avrdude tells me the signature is wrong, whenever I try it with 168. Might that already be an indicator for something being wrong!? I ordered a 168 and it's printed on the chip, so it should be an actual 168.
Furthermore I noticed that I can only use the Baud rate of 115200, but I read that only 19200 should be correct and when I use that I get no response as well.
This is the command I'm trying to use:
avrdude -Cavrdude.conf -patmega328p -PCOM3 -carduino -b115200 -U efuse:w:0x00:m -U hfuse:w:0xDD:m -U lfuse:w:0xFF:m

And the response I get is:
avrdude: verifying ...
avrdude: verification error, first mismatch at byte 0x0000
         0x00 != 0xdd
avrdude: verification error; content mismatch

I tried different software and different USB cables, to no avail.
If anyone could provide any direction I can try and look for a solution or mistakes I might have made, I'd be really grateful!

I got an answer on another forum. I was missing a 10μF capacitor between the Ground and Reset of the Arduino. Not a single documentation, image or video I saw mentioned that. Everything works fine now.

so you could burn the bootloader without the capacitor, but not set fuses?

This official doc mentions the capacitor in the text. Though it is not very clear and is not shown in the wiring diagrams. The official Arduino docs are often not that good

@Juraj It seems that I was addressing the ATMega328p on the Arduino itself the whole time so I probably uploaded everything to that instead of the 168.

@chrisl Thanks for pointing that out! Apparently it's also sufficient to directly bridge the +5V and Reset pin, but I haven't treid that, yet.

it is not possible to burn bootloader to the as ISP programmer Arduino

Alright. The burning process went through without error, though, and I also got verification at the end. So no idea where that data went, was just my guessing :)


text:
Why i am not getting the decimal number as output? The code is explained with the help of comments
// Defined three array arr0,arr1,arr2
int arr0[] = {0, 0, 0, 0, 0, 0, 0, 0};
int arr1[] = {0, 0, 0, 0, 0, 0, 0, 0};
int arr2[] = {0, 0, 0, 0, 0, 0, 0, 0};

//cord function takes binary number array as input and returns decimal
//number to a single variable as output
int cord(int a[]) {
  int v = 0;
  for (int i = 0; i < 8; i++)
  {
    int p = 1;
    for (int j = 0; j < i; j++)
    {
      p = p * 2;
    }
    v = v + a[i] * p;
  }
  return v;
}

//function bcord takes input row & col and updates the value in arr0,arr1,arr2 to 1 wherever
// there is some value in the row and column coordinate Eg.2,0 will make 2nd index of arr0
// to 1 or 2,1 will make 2nd index of arr1 to 1
int bcord(int row[], int col[])
{

  int n = sizeof(col) / sizeof(col[0]);

  for (int i = 0; i < n; i++)
  {
    int j;
    if (col[i] == 2)
    {
      j = row[i];
      arr2[j] = 1;
    }
    if (col[i] == 1)
    {
      j = row[i];
      arr1[j] = 1;
    }
    if (col[i] == 0)
    {
      j = row[i];
      arr0[j] = 1;
    }
  }
  int led0 = cord(arr0);
  Serial.print(led0);
  int led1 = cord(arr1);
  Serial.println(led1);
  int led2 = cord(arr2);
  Serial.println(led2);
  return 0;
}

void setup()
{
  Serial.begin(9600);
  int row[] = {0, 0, 2, 2, 1};
  int col[] = {0, 1, 0, 1, 1};
  bcord(row, col);
}

void loop() {}
// Output expected is decimal numbers which are stored in led0, led1 and led2 on the serial
// monitor

what output are you getting?

your code is improperly formatted ... code that should be indented, isn't indented ... code that should not be indented, is indented ... it's a mess

I just used the autoindent function of the Arduino IDE. You should make more use of it, because correct indenting comes in very handy to find certain syntax errors.

Thank you jsotola, Chrisl & Edgar! But i get 57 and then 0 in next line as output. How can i get the decimal values stored in led0, led1 and led2?

“570” is correct: led0 is 5, led1 is 7 and led2 is 0.

Thank you Edgar, i totally missed that!

In C++, you cannot pass an array as a parameter to a function. When you
write the function prototype
int bcord(int row[], int col[], int n)

the compiler considers it a synonym of:
int bcord(int *row, int *col, int n)

In other words, both row and col are pointers, not arrays.
When you call the function like this:
bcord(row, col);

the compiler implicitly converts the call into this:
bcord(&row[0], &col[0]);

In other words, you are really passing pointers to the first element of
each array. This is a standard language behavior called “decay to
pointer”.
When I compile your code with warnings enabled, I get the following:
In function 'int bcord(int*, int*)':
warning: 'sizeof' on array function parameter 'col'
will return size of 'int*' [-Wsizeof-array-argument]
   int n = sizeof(col) / sizeof(col[0]);
                     ^
arr-ind.ino:31:30: note: declared here
 int bcord(int row[], int col[])
                              ^

Thus the compiler is telling you what is wrong. The variable n is not
what you expect.
The standard solution is to pass the size of the array from the caller:
move the definition of n to setup(), define bcord() as:
int bcord(int row[], int col[], int n)

and call it as
bcord(row, col, n);


text:
Keyboard commands not working?
So I've been trying to use Mouse.move();
and Keyboard.press();. Every time I try to send it to my Arduino(mega 2560) it says keyboard or mouse was not declared. Any solutions?
  #include <Keyboard.h>
void setup() {

  pinMode(2, INPUT);

}

void loop() {

  if (digitalRead(2) == HIGH) {
    Keyboard.begin();
    Keyboard.press(KEY_LEFT_ARROW);
  }
if(digitalRead(2)==LOW){
  Keyboard.end();

}

}

Yes, don't use a Mega2560. Instead use one of the boards the Keyboard and Mouse libraries are designed to work with. I.e., one that actually has a USB connection...!


text:
Arduino ESP8266WebServer hangs after a while but responds pings
I have an ESP8266 module that I use to be able to power on three computers if they are off. The ESP8266WebServer has what I needed to have a POST method rather than a simpler GET one since I am sending a password and I want that little extra security.
The code works and the circuits work as expected but only for a while. I have not been able to track down what is happening but whatever I do, it always hangs after some time but only the web server, it stills continues to respond pings so I know it is still connected and the serial monitor writes back my debug texts.
What I have tried after researching for some time:

The HTML output string probably gets too big for the memory and should use PROGMEM but in the end, I sill need to manipulate it and something breaks. Gave up on it.
The HTML output had an embedded image for the logo that also probably gets too big for the memory. Erased the image but stills hangs about the same time with or without it.
Looked for a way to hardreset the ESP8266 module, could not find how and it is surely bad practice and may come with other kind of problems.
Add a timeout for the connection, did not make any difference either.

I am missing something with the handle of the web server that gets the memory or something full and it stops answering request after a while because of it.
Here is the code:
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

const char* ssid     = "";
const char* password = "";
const char* hostname = "";
const String imgLogo = "";

ESP8266WebServer server(9080);

String header = "";

String output1State = "off";
String output2State = "off";
String output3State = "off";

const int output1 = D1;
const int output2 = D2;
const int output3 = D8;

const int input1 = D5;
const int input2 = D6;
const int input3 = D7;

const int ledPin =  LED_BUILTIN;

unsigned long currentTime = millis();
unsigned long previousTime = 0;
const long timeoutTime = 2000;

unsigned long previousMillisOff = 0;
unsigned long previousMillisOn = 0;
unsigned long previousMillisMsg = 0;

void setup() {
  Serial.begin(9600);
  pinMode(output1, OUTPUT);
  pinMode(output2, OUTPUT);
  pinMode(output3, OUTPUT);
  pinMode(input1, INPUT);
  pinMode(input2, INPUT);
  pinMode(input3, INPUT);

  digitalWrite(output1, LOW);
  digitalWrite(output2, LOW);
  digitalWrite(output3, LOW);

  WiFi.disconnect();
  delay(500);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, HIGH);

  WiFi.mode(WIFI_STA);
  WiFi.hostname(hostname);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
    digitalWrite(ledPin, !digitalRead(ledPin));
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println(WiFi.getAutoConnect());
  digitalWrite(ledPin, HIGH);

  server.on("/", HTTP_GET, handleRoot);
  server.on("/serverAction", HTTP_POST, serverAction);
  server.onNotFound(handleNotFound);

  server.begin();
  Serial.println("HTTP server started");
}

void loop(void)
{
  server.handleClient();

  unsigned long currentMillis = millis();
  if(currentMillis - previousMillisOff > 5000)
  {
    previousMillisOff = currentMillis;
    digitalWrite(ledPin, LOW);
    previousMillisOn = currentMillis;
  }

  currentMillis = millis();
  if(!digitalRead(ledPin) && currentMillis - previousMillisOn > 250)
  {
    previousMillisOn = currentMillis;
    digitalWrite(ledPin, HIGH);
    previousMillisOff = currentMillis;
  }

  currentMillis = millis();
  if(currentMillis - previousMillisMsg > 30000)
  {
    Serial.println(WiFi.localIP());
    previousMillisMsg = currentMillis;
  }
}

void handleRoot()
{
  boolean PC01 = digitalRead(input1);
  boolean PC02 = digitalRead(input2);
  boolean PC03 = digitalRead(input3);

  String HTML = String("<!DOCTYPE html>\r\n\r\n") +
    " \r\n    <meta charset=\"UTF-8\">\r\n    <meta http-equiv=\"cache-control\" content=\"no-cache, must-revalidate, post-check=0, pre-check=0\" />\r\n    <meta http-equiv=\"cache-control\" content=\"max-age=0\" />\r\n   <meta http-equiv=\"expires\" content=\"0\" />\r\n   <meta http-equiv=\"expires\" content=\"Tue, 01 Jan 1980 1:00:00 GMT\" />\r\n    <meta http-equiv=\"pragma\" content=\"no-cache\" />\n\r   <link href=\"data:image/x-icon;base64," + imgLogo + "\" rel=\"icon\" type=\"image/x-icon\" />\r\n   \r\n \r\n \r\n    \r\n\r\n
Server switch
\r\n  " +
    "
Estado PC01 - " + (PC01 ? "Encendido" : "Apagado") + "\r\n" +
    "
\r\n" +
    "   <form action=\"/serverAction\" method=\"post\">\r\n" +
    "     Contraseña: <input type=\"password\" name=\"pwd\">\r\n" +
    "
\r\n" +
    "     <input type=\"text\" name=\"server\" value=\"PC01\" hidden>\r\n" +
    "     <button class=\"button " + (PC01 ? "" : "button2") + "\" type=\"submit\"" + (PC01 ? " disabled> PC01 encendido" : ">Encender PC01") + "</button>\r\n" +
    "   </form>\r\n\r\n" +
    "
Estado PC02 - " + (PC02 ? "Encendido" : "Apagado") + "\r\n" +
    "
\r\n" +
    "   <form action=\"/serverAction\" method=\"post\">\r\n" +
    "     Contraseña: <input type=\"password\" name=\"pwd\">\r\n" +
    "
\r\n" +
    "     <input type=\"text\" name=\"server\" value=\"PC02\" hidden>\r\n" +
    "     <button class=\"button " + (PC02 ? "" : "button2") + "\" type=\"submit\"" + (PC02 ? " disabled> PC02 encendido" : ">Encender PC02") + "</button>\r\n" +
    "   </form>\r\n\r\n" +
    "
Estado PC03 - " + (PC03 ? "Encendido" : "Apagado") + "\r\n" +
    "
\r\n" +
    "   <form action=\"/serverAction\" method=\"post\">\r\n" +
    "     Contraseña: <input type=\"password\" name=\"pwd\">\r\n" +
    "
\r\n" +
    "     <input type=\"text\" name=\"server\" value=\"PC03\" hidden>\r\n" +
    "     <button class=\"button " + (PC03 ? "" : "button2") + "\" type=\"submit\"" + (PC03 ? " disabled> PC03 encendido" : ">Encender PC03") + "</button>\r\n" +
    "   </form>\r\n \r\n";

  server.send(200, "text/html", HTML);

}

void serverAction()
{

  if( ! server.hasArg("pwd") || ! server.hasArg("server") || server.arg("pwd") == NULL || server.arg("server") == NULL)
  {
    server.send(400, "text/plain", "400: Invalid Request");
    return;
  }

  if(server.arg("pwd") == "0123456789")
  {
    String redirect = String("");
    if(server.arg("server") == "PC01")
    {
      if(!digitalRead(input1))
      {
        server.send(200, "text/html", "
Encendiendo " + server.arg("server") + "
" + redirect);
        digitalWrite(output1, HIGH);
        delay(1000);
        digitalWrite(output1, LOW);
      }
      else
        server.send(200, "text/html", "
" + server.arg("server") + " ya encendido
" + redirect);

    }
    else if(server.arg("server") == "PC02")
    {
      if(!digitalRead(input2))
      {
        server.send(200, "text/html", "
Encendiendo " + server.arg("server") + "
" + redirect);
        digitalWrite(output2, HIGH);
        delay(1000);
        digitalWrite(output2, LOW);
      }
      else
        server.send(200, "text/html", "
" + server.arg("server") + " ya encendido
" + redirect);
    }
    else if(server.arg("server") == "PC03")
    {
      if(!digitalRead(input3))
      {
        server.send(200, "text/html", "
Encendiendo " + server.arg("server") + "
" + redirect);
        digitalWrite(output3, HIGH);
        delay(1000);
        digitalWrite(output3, LOW);
      }
      else
        server.send(200, "text/html", "
" + server.arg("server") + " ya encendido
" + redirect);
    }
    else
    {
      server.send(401, "text/plain", "401: Unauthorized");
    }
  }
  else
  {
    server.send(401, "text/plain", "401: Unauthorized");
  }
}

void handleNotFound(){
  server.send(404, "text/plain", "404: Not found");
}

Any suggestions would be appreciated.

When you use String the way you do, you're doing a lot of memory allocations. The ESP8266 doesn't have a lot of memory and is easily subject to a problem called "heap fragmentation" - memory is allocated from a fixed pool called a "heap". Over time the free parts of the heap may become so fragmented that you can no longer allocate chunks of memory over a certain size. The way that you're building the string in the variable HTML will probably cause this to happen quickly.
To check for heap fragmentation, add this code to the end of handleRoot():
  Serial.print("getFreeHeap: ");
  Serial.println(ESP.getFreeHeap());
  Serial.print("getHeapFragmentation: ");
  Serial.println(ESP.getHeapFragmentation());
  Serial.print("getMaxFreeBlockSize: ");
  Serial.println(ESP.getMaxFreeBlockSize());

And use your web server, especially reloading the root page, until you see the problem happen.
If you have a memory leak (memory is being allocated but never freed), you'll see getFreeHeap drop and not go back up.
If you have heap fragmentation, you'll see getMaxFreeBlockSize get smaller until it's smaller than the biggest strings you're trying to allocate (probably the total length of the root web page). You'll also see getHeapFragmentation get bigger over time - it's a metric from 0 to 100% of how fragmented the heap is. If it gets to 40 or 50% you're in trouble.
If you are seeing heap fragmentation you're going to need to rethink the way you build the web page you're serving. You need to minimize the number of times that you allocate memory. You may not know it but every time you add something on to a String, it frees the memory for the old string and allocates memory for the new one.
For instance, you build the web page like this:
 String HTML = String("<!DOCTYPE html>\r\n\r\n") +
    " \r\n    <meta charset=\"UTF-8\">\r\n    <meta http-equiv=\"cache-control\" content=\"no-cache, must-revalidate, post-check=0, pre-check=0\" />\r\n    <meta http-equiv=\"cache-control\" content=\"max-age=0\" />\r\n   <meta http-equiv=\"expires\" content=\"0\" />\r\n   <meta http-equiv=\"expires\" content=\"Tue, 01 Jan 1980 1:00:00 GMT\" />\r\n    <meta http-equiv=\"pragma\" content=\"no-cache\" />\n\r   <link href=\"data:image/x-icon;base64," + imgLogo + "\" rel=\"icon\" type=\"image/x-icon\" />\r\n   \r\n \r\n \r\n    \r\n\r\n
Server switch
\r\n  " +
    "
Estado PC01 - " + (PC01 ? "Encendido" : "Apagado") + "\r\n" +
    "
\r\n" +
    "   <form action=\"/serverAction\" method=\"post\">\r\n" +

Every time you use + to add to the String here, you're causing the compiler to unnecessarily allocate memory. It's completely unnecessary to add most of these strings together. The C++ compiler will automatically concatenate strings written on separate lines, like so:
 String HTML = String("<!DOCTYPE html>\r\n\r\n") +
    " \r\n    <meta charset=\"UTF-8\">\r\n    <meta http-equiv=\"cache-control\" content=\"no-cache, must-revalidate, post-check=0, pre-check=0\" />\r\n    <meta http-equiv=\"cache-control\" content=\"max-age=0\" />\r\n   <meta http-equiv=\"expires\" content=\"0\" />\r\n   <meta http-equiv=\"expires\" content=\"Tue, 01 Jan 1980 1:00:00 GMT\" />\r\n    <meta http-equiv=\"pragma\" content=\"no-cache\" />\n\r   <link href=\"data:image/x-icon;base64," + imgLogo + "\" rel=\"icon\" type=\"image/x-icon\" />\r\n   \r\n \r\n \r\n    \r\n\r\n
Server switch
\r\n  "
    "
Estado PC01 - " + (PC01 ? "Encendido" : "Apagado") + "\r\n"
    "
\r\n"
    "   <form action=\"/serverAction\" method=\"post\">\r\n"

Just making that change will reduce the heap fragmentation. This won't solve the problem but it should allow your program to run longer without crashing.
This is a big subject. The best way to do it is to use C strings (character arrays) and avoid allocating memory altogether, but this is difficult and tedious even for experienced programmers. The ESP8266 Arduino Core documentation offers some advice (see the section "Memory, memory, memory"), including using PROGMEM for constant literal strings and creating String objects with all the space they'll need when they're allocated, to avoid freeing and re-allocating the internal buffer they use to store the string.
If you're having heap fragmentation issues, do everything you can to reduce String use in your program. If that doesn't get your web server working reliably, search the web and Stack Overflow for more advice on how to avoid heap fragmentation, and post new questions here about specific issues.

You still have a + in the string concatenation example on the first line. Otherwise this is good advice...

Hi, thank you and sorry for not getting back here sooner. I will try what you suggest and give a follow up of what is going with this.

i bet $20 is the String (mis)usage...


text:
Assign a delay value generated by a random function called randomBlink()
I'm trying to make a sketch where my led blinks with random delay. I have 2 functions: ledBlink() and randomBlink(). The randomBlink use as delay parameter a random number "r" generated from 1 to 499 and pass this value to the ledBlink function to make the led blink with a delay according the random number generated. But seems like that led  doesn't consider the random value of blinkDelay. Any help is appreciated, thank you so much!
#include <JC_Button.h>

int ledPin = 11;

int ledState = LOW;
unsigned long blinkDelay;
unsigned long lastBlinkMillis = 0;

void setup() {

  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
}

void ledBlink()
{
  unsigned long currentMillis = millis();

  if (currentMillis - lastBlinkMillis >= blinkDelay)
  {
    // save the last time you blinked the LED
    lastBlinkMillis = currentMillis;

    // if the LED is off turn it on and vice-versa:
    ledState = !ledState;

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  }
}

void randomBlink()
{
  unsigned long r = random(500);
  blinkDelay = r;
  ledBlink();

}

void loop() {
  randomBlink();
}

you may like this https://github.com/jandrassy/SunriseClock/blob/6ad596040e6a87d569ffaacddd7988803fc5d376/SunriseClock/SunriseClock.ino#L687

set a busy flag at begining of ledBlink() ... clear it inside of the if block ... call randomBlink() only if not busy

Your problem descriptions is a bit unclear, though I think I see your problem.
On every loop() iteration you call randomBlink(), which generates a new random delay value and then calls ledBlink(), which in turn checks millis() for the time to toggle the LED and exits fast. So you are blinking only when the current blinkDelay has passed, but you generate new random values for blinkDelay on every loop() iteration - so really really fast. In the time needed for even the small delays you may have generated thousands of new random values, so it is very likely that some of them are rather small values. You check against these so you only get short delays.
Think of how you would do such thing in real life. Lets say you use a dice to determine the numbers of minutes to wait. You are throwing the dice every few seconds while watching the clock. Chances are that you will at some point get a 1 or 2 after waiting 1 or 2 minutes. It is unlikely that you don't get a 6 for 6 minutes straight. Instead you would want to through the dice only once per waiting period.
For the code this means, that you need to restructure it. Calculate the new delay value only when you toggle the LED. So something like this:
void ledBlink()
{
  unsigned long currentMillis = millis();

  if (currentMillis - lastBlinkMillis >= blinkDelay)
  {
    // save the last time you blinked the LED
    lastBlinkMillis = currentMillis;

    // if the LED is off turn it on and vice-versa:
    ledState = !ledState;

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);

    // generate new random delay
    randomBlink();
  }
}

void randomBlink()
{
  unsigned long r = random(500);
  blinkDelay = r;
}

void loop() {
  ledBlink();
}

Calling ledBlink() in every loop() iteration makes sure, that the toggling of the LED actually happens. A new random value for the delay is only called after the LED just got toggled. Now the range of the delay will be the full 499ms.

oh ok, gotcha! thanks!


text:
Multiplexer 74HC4067, conflict between channels
I am currently working on an Arduino Zero with a 74HC4067 multiplexer and I am experiencing inconsistencies when testing some of the channels.
My class is the following (it should be functional for 8 or 16 channels multiplexers).
Multiplexer.h :
#ifndef Multiplexer_h
#define Multiplexer_h

#include "Arduino.h"

class Mux
{
  public:
    Mux(uint8_t numberOfChannels, byte sigPin, byte adress1, byte adress2, byte adress3, byte adress4 = 0);

    uint8_t muxRead(byte pin);//Read specific mux pin
    void selectMuxPin(byte pin);

  private:
    uint8_t m_numberOfChannels;
    byte m_sigPin ;
    byte m_adress1 ;
    byte m_adress2 ;
    byte m_adress3 ;
    byte m_adress4 ;
    uint8_t m_numberOfAdressPins;
};

#endif

Multiplexer.cpp :
#include "Multiplexer.h"

//**************************************************************

Mux::Mux(uint8_t numberOfChannels,
         byte sigPin,
         byte adress1,
         byte adress2,
         byte adress3,
         byte adress4)

:   m_numberOfChannels(numberOfChannels),
    m_sigPin(sigPin),
    m_adress1(adress1),
    m_adress2(adress2),
    m_adress3(adress3),
    m_adress4(adress4)
{
  if(m_numberOfChannels > 8) {m_numberOfAdressPins = 4;}
  else {m_numberOfAdressPins = 3;}

  //Set adresses to OUTPUT
  pinMode(m_adress1, OUTPUT);
  pinMode(m_adress2, OUTPUT);
  pinMode(m_adress3, OUTPUT);
  if(m_numberOfChannels > 8){pinMode(m_adress4, OUTPUT);};

  //Set adresses to LOW
  digitalWrite(m_adress1, LOW);
  digitalWrite(m_adress2, LOW);
  digitalWrite(m_adress3, LOW);
  if(m_numberOfChannels > 8){digitalWrite(m_adress4, LOW);};

  pinMode(m_sigPin, INPUT_PULLUP);
}

//**************************************************************

uint8_t Mux::muxRead(byte pin)
{
  selectMuxPin(pin);
  bool value = digitalRead(m_sigPin);
  return(value) ;
}

void Mux::selectMuxPin(byte pin)
{
  const int selectPins[4] = {m_adress1, m_adress2, m_adress3, m_adress4};
  if (pin > (m_numberOfChannels - 1)) return; // Exit if pin is out of scope

  for (int i = 0; i < m_numberOfAdressPins; i++)
  {
    if (pin & (1<<i)) {digitalWrite(selectPins[i], HIGH);}
    else {digitalWrite(selectPins[i], LOW);}
  }
}

To make my tests on the 74HC4067, I connect my multiplexer, I put the pin 8 of my Arduino to the "LOW" state and with the help of a jumper cable I test each of the pins via the following code:
#include "Multiplexer.h"

//**************************************************************

Mux Mux0(16, 6, 2, 3, 4, 5);

//**************************************************************

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

//**************************************************************

void loop() {

  //Set pin 8 to LOW for the test with a jumper
  analogWrite(8, LOW);

  //For this test, we print the name of the multiplexer's channel if it's LOW

  bool channel0 = Mux0.muxRead(0);
  if(!channel0)
    Serial.println("Channel 0");

  bool channel1 = Mux0.muxRead(1);
  if(!channel1)
    Serial.println("Channel 1");

  bool channel2 = Mux0.muxRead(2);
  if(!channel2)
    Serial.println("Channel 2");

  bool channel3 = Mux0.muxRead(3);
  if(!channel3)
    Serial.println("Channel 3");

  bool channel4 = Mux0.muxRead(4);
  if(!channel4)
    Serial.println("Channel 4");

  bool channel5 = Mux0.muxRead(5);
  if(!channel5)
    Serial.println("Channel 5");

  bool channel6 = Mux0.muxRead(6);
  if(!channel6)
    Serial.println("Channel 6");

  bool channel7 = Mux0.muxRead(7);
  if(!channel7)
    Serial.println("Channel 7");

  bool channel8 = Mux0.muxRead(8);
    if(!channel8)
    Serial.println("Channel 8");

  bool channel9 = Mux0.muxRead(9);
  if(!channel9)
    Serial.println("Channel 9");

  bool channel10 = Mux0.muxRead(10);
  if(!channel10)
    Serial.println("Channel 10");

  bool channel11 = Mux0.muxRead(11);
  if(!channel11)
    Serial.println("Channel 11");

  bool channel12 = Mux0.muxRead(12);
  if(!channel12)
    Serial.println("Channel 12");

  bool channel13 = Mux0.muxRead(13);
  if(!channel13)
    Serial.println("Channel 13");

  bool channel14 = Mux0.muxRead(14);
  if(!channel14)
    Serial.println("Channel 14");

  bool channel15 = Mux0.muxRead(15);
  if(!channel15)
    Serial.println("Channel 15");
}

For most of the channels it works quite well. When I connect the jumper (pin 8) to a channel of the multiplexer, the name of the corresponding pin is displayed in the console.
However, two channels are problematic. Channel 0 and channel 8. No matter if I connect the jumper to one or the other, I see in the console "Channel 0" and "Channel 8" as if both were connected and the change of state of one would cause the change of state of the other.
Any idea why?
Thanks

I have no idea why. You might want to check the levels on any relevant pin manually with some voltage meter and change the selection via the serial monitor.

Hmm... analogwrite(8,LOW) I´d rather use digitalwrite()

I gather it is part of a learning experiment. Logically this does not compute however there are many reasons something like this could happen. A bad IC is the first thing that comes to mind but they are generally very rugged devices. If you have a scope probe the power supplies to be sure they are clean and stable, if so start by holding it in one of the bad states and take voltage measurements on VCC, Ground, several other pins and the related pins. Your voltage on each pin should be within 0.1V of the appropriate power supply pin.  If not it would indicate a short especially if it goes somewhere mid supply voltage. If this is a breadboard flip the bad pins out and test again. If everything is in speck it is a short, if it still show you probably have a bad IC.

Thank you for your answer (and sorry for my late answer...). After some tests and research I think that the problem comes from the hardware. I prototype on SMD multiplexers that I buy already soldered on a small IC. There must be a problem in the design of the IC that generates interference between the channel 0 and channel 8 track... I have no scope but I'll try to do some tests with a multimeter, this should already give me some indications.

I have done additional tests with the same component but proposed by another supplier and it works perfectly. So the problem was in the hardware.