text:
ESP32 Low Power Reconnect Latency Question
I am trying to develop a small 9-button BLE keyboard on the ESP32 with a rotary encoder as a volume knob. My question involves the low power modes and the time it takes for them to wake up.
My system enters sleep mode after 5 seconds of inactivity from the user.
The issue is when the ESP wakes up from light sleep - it takes around 1 to 2 seconds for bluetooth to reconnect, and the keystroke or action that woke it up isn't processed.
How can I address the issue of a faster reconnect? I want the system to save power when it is not in use, but I also wish for it to be responsive when coming out of this low-power state to process user requests.
Here is the processing block:
while (true) {
    //Begin sleep if user has not interacted for >= 5 seconds
    current_sys_time = millis();
    if (current_sys_time - last_sys_event_time > MAX_ALLOWED_IDLE_TIME)
        light_sleep_begin();

    //Play/pause media when rotary encoder switch is pressed
    if (digitalRead(PIN_SW) == LOW && play_pause_btn == NOT_PRESSED) {
        delay(25);
        if (digitalRead(PIN_SW) == LOW)
            play_pause_btn = WAS_PRESSED;
        last_sys_event_time = millis();
    }
    else if (digitalRead(PIN_SW) == HIGH && play_pause_btn == WAS_PRESSED) {
        last_sys_event_time = millis();
        play_pause_btn = NOT_PRESSED;
        bleKeyboard.write(KEY_MEDIA_PLAY_PAUSE);
    }

    //Turn volume up or down when encoder is turned clockwise or ocunter-clockwise, respectively
    if (encoder_read()) {
        if (encoder_4bit_sample == CLOCKWISE)
            bleKeyboard.write(KEY_MEDIA_VOLUME_UP);
        else if (encoder_4bit_sample == COUNTER_CLOCKWISE)
            bleKeyboard.write(KEY_MEDIA_VOLUME_DOWN);
    }
}

And here is my sleep function:
void light_sleep_begin()
{
    gpio_wakeup_enable(GPIO_NUM_33, GPIO_INTR_LOW_LEVEL); //Encoder SW pin
    gpio_wakeup_enable(GPIO_NUM_35, GPIO_INTR_LOW_LEVEL); //Encoder CLK pin
    gpio_wakeup_enable(GPIO_NUM_32, GPIO_INTR_LOW_LEVEL); //Encoder DT pin
    esp_sleep_enable_gpio_wakeup();

    esp_light_sleep_start();
}

Board: ESP32 DevkitC \
IDE: PlatformIO \
Module: ESP32 WROOM

I don't think the failure to process the input is due to any bluetooth reconnection issue. Have you tried placing a print within your IF block so that you know as soon as the ESP observes a button press?

@TisteAndii Yeah, the thing is that when light sleep is called, I see the ESP disconnect from the slave device, and when it wakes up it takes ~2 seconds to re-establish the connection. There has to be a quicker wake-up time :/

Waking up likely isn't what is taking 2 seconds. That's why I'm saying you should time it, to narrow down exactly what's going on. Place a print(millis()) immediately before and after light_sleep_begin() so you know how long that's taking. Place another inside the IF block so you know when the button press gets noticed, BLE connection or not. Then post what you find.

Hey, sorry I was being ambiguous with my use of the phrase "wake up". I was talking about the time it takes for BLE to re-connect the ESP to the computer after sleeping. Anyways, I took your advice and placed a Serial.println(millis()); before and after light_sleep_begin(); The difference between the first and second print is how long it was sleeping before being waken up. It changes each time depending on how long I let it sleep. The button press gets noticed instantly.

Okay, that's good news. The button events are instantly noticed, problem is sending them ASAP after waking up. When you enter light sleep, the radios are turned off so upon waking up, I expect it'll take a while for the radio to resume advertising and for your PC (or whatever your client is) to connect to the ESP32. All these small delays add up and represent the cost of going to sleep in the first place. You can try saving the button press event(s) in some array until the connection is up (isConnnected()) and then send them. Or raise an issue on the library's Github, seems responsive.

@TisteAndii Ok. That makes sense. I appreciate your help.


text:
HID with bidirectional communication
I want to build a gamepad HID using the Arduino Micro, and intend to use Nico’s HID library for that.
But I would like to send some config info from the PC to the Arduino HID as well.
Can you have a gamepad that not only sends state to the PC, but also receives a configuration from the PC?
I intend to use this with a Linux PC as host.

Yes, but the configuration side of things will not be part of the gamepad HID.  You will need to set up a second communication channel - be that serial or raw HID - to do the configuration.

source: Stack Exchange

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

sort: votes


text:
Can i exchange my arduino nano for an atmega328p-pu in my project?
Im currently trying to make a smart light switcher that is attached in front of my rooms light switches. It basically mostly consists of two servos (to turn on or off either switch), two button (to turn the servo manually), an esp8266 esp-01 module (to be able to use with a google home) and my arduino nano. I really need to make it as small as posible and i also want to keep my only arduino not attached to the wall. Would it work if i use an atmega328p or like an attiny84a to replace the arduino?
Im not finished with connecting the esp-01 to the arduino but i was thinking of using the arduino's 3.3v output pin. Would i need extra components to run the microcontroller on its own?
Im really new to arduino and im trying to learn the most I can and to try to make my little project as good as i can.
Would really appreciate some help please, thank you!

This article might help you. It is specially for the Atmega328p and for setting up the complete Arduino, but it explains all the important things

The 3.3V output is on the board.  You’re not going to get that from the chip   The chip doesn’t have its own regulator.  I doubt the 3V3 pin could push an ESP anyway.  They pull a good bit of current.

ESP-01 could consumed as much as 170mA burst, all the Arduino Boards (I only have Leonardio, Nano and Pro Micro) that I have can't supply enough current for the ESP-01.

I use a Pro Mini with a ESP-01 that sit on a tiny self-made 30x23mm adaptor board which includes a LDO regulator for powering both the Pro Mini and ESP-01. Instead of trying to use bare-bone ATMega328p, just get a Pro Mini, it is probably cheaper and not much bigger than the bare-bone when you add the crystal and other components.

Hi @hcheung, would you mind showing how you made your project or where you found the information of connecting the ESP-01 to a Pro Mini? I decided to buy the board since its smaller but im still not sure how to use the module. Thanks

Pro Mini is just like a Nano, except it does not has the USB interface and you have to use a USB-TTl adaptor to upload Arduino Sketch. For ESP-01, I forked a library that utilising AT Command communication between Pro Mini and ESP-01. But on a recent project, I use a hybrid approach for both ESP-01 and an STM32 boards running Arduino sketch and communicate via serial, you can read about my approach at here.

Sure you can - as long as you include the rest of the support circuitry.
However the ESP-01 beats the Arduino hands-down and can do everything the Arduino does by itself - except it lacks IO so connecting to the servo and button could be tricky.
So using some kind of extra MCU as an IO expansion over serial would be a good idea, but a 328P is rather more than you need. Maybe you should look at something smaller, such as one of the ATTiny chips.

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


text:
Is it dangerous to connect two output pins together?
If I have two output pins, one set high and the other set low with digital or analog write like this
digitalWrite(PIN1, LOW);
digtialWrite(PIN2, HIGH);

and then I short them together using a wire, will current flow through the wire?

will current flow through a wire if you connect the positive and negative terminals of a battery?

Oh yeah. So a large amount of current will flow which could damage the arduino.

Yes. It is dangerous. You can imagine what would happen when you understand how a GPIO pin works in output mode.
You are effectively connecting VCC to GND via two small and weak MOSFETs which will overheat and break down.

You can connect but requires resistor between two pins to limit the current.

It depends on what you try to achieve. If you want to demonstrate what happens without a resistor, and you're ready to accept possible damages, you can connect two output pins directly, and drive different levels.

That's out of spec for any arduino microcontroller.
The behavior of a broken Arduino is "undefined" :)
I guess there will not flow current (after an initial peak), but at least one of the two pins is not working properly any more. But, this is just a guess.
And it's probably not dangerous for you or the connecting wire (Other than @jsotola's comparison with a shorted battery in a comment to your question). I guess the arduino will die before it gets dangerously hot.

Shorting the output pins together is a bad idea that will likely result in damage to your Arduino. According to specifications, the I/O pins are able to source (provide current to a load) or sink (accept current from an external source) up to 40mA. In almost all cases, you will want to use a current-limiting resistor. In some cases, an external circuit that you connect your Arduino to may intrinsically limit the current.
In the case of lighting up an LED, you can do this in two ways:

Set the I/O pin HIGH to source current to the LED through a current-limiting resistor to ground. The I/O pin provides the current to light up the LED. LOW turns it off.
Set the I/O pin LOW to sink current from the LED and current-limiting resistor where the power to the LED is provided by the external source. In this case, the LED floats and the I/O pn serves as ground. HIGH turns it off.

The internal pullup resistor is useful if you want to be able to drive an external transistor or logic level device.
This Arduino tutorial goes into more detail about the specific modes of operation.


text:
MPU-9250 compass always returns to zero
I am trying to build a 9-DOF IMU using the MPU-9250 chip which contains a gyro, accelerometer and compass. I have successfully realized 6-DOF sensor fusion using the DMP chip and Sparkfun's library, but I still have some yaw drift which is why I want to use its onboard compass for 9-DOF.
The DMP unfortunately can't do that so I tried kriswiner's work on 9-DOF sensor fusion which seemed to work but after I rotate the PCB, the yaw moves in the correct direction but it then slowly returns back to where it started, without me moving the PCB any more. This happens with many different sensor fusion libs, some more some less severe.
I have also tried just reading the raw mx and my values and reading the heading using atan2(my, mx) which made things a little better but still a 360° real-life rotation did not correspond at all to a 360° rotation on the chip.
Is this a known problem with the MPU-9250 and I am missing something completely obvious, or what could be wrong here?
Thank you for any help!

Ok, I have finally found the issue, and I am feeling very, very stupid.

I needed to calibrate the magnetometer with the figure-8 movement
I put a gigantic solid-metal 18650 Li-ion cell right next to the magnetometer chip...

EDIT: after replacing the 18650 with a polymer battery that is far away from the chip, things got a little better but both sensors in both devices still return garbage values.


text:
What current is safe for Wemos d1?
I've got 12V / 400mA power supply for my Wemos D1 R1, and I'm using VIN output(I need 12V for led strip). I need to change this power supply because of color, and I can't find similiar with the same parameters. The question is - Is power supply with 12V / 1A - 2A safe to use?

Yes. The quoted current of a power supply is the upper limit of what it is capable of providing.

With very few exceptions, electronic devices only draw as much current as they need, limited by their resistance.
The current rating on a power supply is the MAX current it can provide before the voltage drops. Having a higher current power supply may waste energy, but won't hurt anything.
According to Ohms law, V = IR
Where V = Voltage
I = current, in amps
R = resistance, in ohms
(voltage = current times resistance.)
Or, solving for current:
I = V/R

current = voltage divided by resistance.
So if you have a 12 volt power supply, and a 100 ohm resistor, you'll get 12/100, or 0.12 amps, flowing through the resistor.

I am a bit confused you state:  VIN output, that is the voltage input to the onboard regulator. For the power supply use one of the same voltage but capable of more current. Current is the maximum a power supply will give reliably. Current is the current needed by a load so if the load is less then the source and the voltages are the same it is a go. The answer is yes either is ok but be sure you have enough current from the power supply + some to cover all of the LEDS.


text:
ESP8266 & 2x VL53L0X Sensors cause WDT resets
I have a system that utilises 2 VL53L0X sensors. This works fine for the majority of time, but after around 20 hours till 2 days (varying), the ESP resets due to Software a WDT, I've managed to do a stack trace, and this is the result:
PC: 0x40100529: Twi::busywait(unsigned char) at /Users/martin/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/core_esp8266_si2c.cpp line 271
EXCVADDR: 0x00000000

Decoding stack results
0x40218f25: Twi::readFrom(unsigned char, unsigned char*, unsigned int, unsigned char) at /Users/martin/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/core_esp8266_si2c.cpp line 405
0x4010083e: millis() at /Users/martin/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/core_esp8266_wiring.cpp line 188
0x4021913c: twi_readFrom(unsigned char, unsigned char*, unsigned int, unsigned char) at /Users/martin/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/core_esp8266_si2c.cpp line 1042
0x402090b0: TwoWire::requestFrom(unsigned char, unsigned int, bool) at /Users/martin/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/libraries/Wire/Wire.cpp line 129
0x402090dc: TwoWire::requestFrom(unsigned char, unsigned char) at /Users/martin/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/libraries/Wire/Wire.cpp line 143
0x402140eb: VL53L0X::readReg(unsigned char) at /Users/martin/Documents/Arduino/libraries/vl53l0x-arduino-1.02/VL53L0X.cpp line 322
0x40214442: VL53L0X::readRangeContinuousMillimeters() at /Users/martin/Documents/Arduino/libraries/vl53l0x-arduino-1.02/VL53L0X.cpp line 816
0x40201f00: readVLXSensors() at /Users/martin/Documents/Arduino/TEST_WS2812/TEST_WS2812.ino line 674
0x402083c7: loop() at /Users/martin/Documents/Arduino/TEST_WS2812/TEST_WS2812.ino line 596
0x40218404: loop_wrapper() at /Users/martin/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/core_esp8266_main.cpp line 172

This is the function that reads the sensors (initiated from the main loop):
void readVLXSensors() {

  if (readTop) {
    distSensorTop_distance = distSensorTop.readRangeContinuousMillimeters();
    if (distSensorTop.timeoutOccurred()) {
      distSensorTop_distance = 99999;
    }
    readTop = !readTop;

  } else {
    distSensorBottom_distance = distSensorBottom.readRangeContinuousMillimeters();

    if (distSensorBottom.timeoutOccurred()) {
      distSensorBottom_distance = 99999;
    }
    readTop = !readTop;
  }

}

As you can see as last desperate measure, I alternate the reading of the sensors, where as before I just read both sensors after each other. But even this approach still gives the WDT resets.
I don't believe it is (my)code nor the VL53L0X Library.. Any one an approach on this one?

It looks like the twi library goes into a tight loop waiting for a response from the sensor, and there's no yield in there.

Thats part of the esp core isn't?

Yep. Make sure you're on the latest version of the core.

Yes I am on 2.6.3

I can see that busywait() doesn't yield, and it doesn't really want to either. Maybe you could add a yield() call just before you query each sensor.

I've changed some things, will have to wait a few days to see the result.


text:
Getting external data to the Arduino
I have a new Uno R3, it's pretty cool and I've enjoyed playing with it.
Now I want to build a couple of things:
1) a market price LCD tracker.
2) a servo motor type thing to open my electric gate.
Both of these either require input from an external website or some kind of message to initiate the action on the Arduino.
How do people generally get data onto the Arduino, I found a lot of conflicting information online.
Does this thing have Wifi or Bluetooth??
I got this pack, it doesn't seem to have either Wifi or Bluetooth, if not how do ppl generally get data onto the Arduino?
I have a raspberry pi spare, can I just use that, sending data from pins?

How do people generally get data onto the Arduino, I found a lot of conflicting information online.

There are various ways depending on what the data is and how you access it.

Does this thing have Wifi or Bluetooth??

Not unless you add WiFi or Bluetooth to it, no.

I have a raspberry pi spare, can I just use that, sending data from pins?

Yes, there are ways.

How you go about getting data on to an Arduino depends very much on how the data is accessed.  It is possible to add a WiFi interface to an Arduino, either through an official WiFi shield or through adding something like an ESP8266 on a breakout board (ESP-01 is popular) although interacting with the ESP8266 can be tricky.
You can do the same with Bluetooth or any number of other wireless protocols.
The simplest method of getting data to the Arduino, though, is through the USB serial port. Since you have a Raspberry Pi available the most logical option would be to plug the Arduino directly into the Pi's USB port. The Pi can then communicate through /dev/ttyACM0 (or /dev/ttyUSB0 for some clones) and the Arduino receive the data through the Serial object. Exactly how you arrange all that is entirely up to you.

Thanks!, so it's valid to use the pi to receive data from the net, process it and send it to the Arduino to display or whatever via USB?  So I guess I wonder is this a known pattern, to use the Pi as data ingress from the web?

Sure, it's perfectly valid. Maybe not common, since the Arduino is probably pretty redundant as the Pi can do most thing natively without needing the Arduino.

ah my plan though is to make a smart gate opener... iPhone Shortcut-->Message Pi over cellular and write data over to Arduino --> Servo Motor, press physical button on gate opener. This way I can give access to anyone to open the gate (via pub/priv key pairs), and I effectively turn one physical fob into a smart remote that can serve many ppl

It depends on the kind of data and where it will be coming from. Trigging your gate really only needs a signal to start moving, though a directional signal would be better ("Open" or "Close"). What is the source of that signal and far from from the gate will it originate?
If you're willing to press a button on the gate, it's a simple matter of sensing the button with one of the Arduino's pins. If you want to operate it from your phone from right in front of the gate, a Bluetooth module on the Arduino could pick up the phone's signal. If you also need to operate it from further away - more than 5-10 meters, a pair of RF modules with stick-antennas like the ones on a WiFi router, might get you 100m.
For the market-price tracker, your data is probably coming from the internet, in which case you'd need either an ethernet module or a WiFi module that would link it to the internet through your local network. Or if this device has to be portable, you could use a cellular module to link it to the internet through the cellular network. This latter is usually expensive - the price of adding an additional line to your cellular plan, for instance.


text:
Can I Interrupt on any keypress on this keypad?
I'm learning how to write code interrupt code. I just experimented with my first toy example that I got from here:
const byte ledPin = 13;
const byte interruptPin = 2;
volatile byte state = LOW;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
}

void loop() {
  digitalWrite(ledPin, state);
}

void blink() {
  state = !state;
}

Now I'm trying to incorporate interrupts into my own project. I have a circuit that looks like this using an Arduino Uno Wifi Rev2, Membrane 3x4 Matrix Keypad, a buzzer, some resistors and an RGB LED:

Can I write code such that it interrupts any time any of the keys is pressed (and I can still tell which key is pressed)? How would I do that?

you could use diodes to connect all the columns to an interrupt pin ... keep all the rows low .... when any button is pressed, an interrupt is generated ... the interrupt would activate a keyboard scan to determine which key caused the interrupt

Uno WiFi Rev 2 supports external interrupt on every pin, but that is not useful here

Interrupt are great for counting things, but taking human input via interrupt can lead to some really confusing code.  You have to start protecting against things getting corrupted because the input comes in the middle of some other part that’s acting on input.  The classic example is a button press.  This line if(buttonState != oldButtonState && buttonState == LOW) is just fine in most code.  But if you use an interrupt to read the button and set buttonState then that line is a huge bug.

see the schematic here ...https://arduino.stackexchange.com/questions/34054/multiple-buttons-on-single-interrupt-how-to-debounce .... since you are using Uno WiFi, you do not need a separate interrupt pin .... just bring all rows low ... pressing any key will interrupt on column pins

Interrupts are for things that happen too fast to sample with normal code.  That doesn’t include a human pressing a button.  Interrupts are NOT a cure for the fact that you’ve coded some other part of the code with blocking functions like delay.  It seems at first like a good idea, but you’ll find out quickly that it would have been much easier to just write non blocking code for things.

No, you can't. Owing to the fact that you have to manually cycle through each row (or column, depending on which way you are holding your head at the time) in order to read which keys are pressed there is no way to relate a button to an interrupt.
The only possible way would be to use an external keypad interface chip (you could roll your own with another Arduino) which has an interrupt signalling facility in it.

Why can't I do what Jsotola mentioned in the comment above?

@SaqibAli, even though it is doable, it is more trouble than it is worth ... but it may be a good learning experience

Yes, that might work, but as jsotola says, it's not worth it. Unless you have a specific reason to require an interrupt just use polling.

"Can't" is too strong. You can if you use diodes, as jsoltola says. "You can, if you wire it correctly using diodes, but coding interrupts is tricky and probably not worth the trouble" would be more accurate.

I mean yeah you “can” put wooden tires on your car.  It would be stupid and counterproductive but you “can” in just the same sense.

You “can” buy dozens of high powered lasers to heat up a pan to make cookies.  It would be cool but terribly expensive and hard to do.  But you “can” in the same sense.  Actually I think laser cookies is probably a better idea.


text:
TLE9879 BLDC shield won't communicate
I just got the TLE9879 BLDC shield, which I connected to an Arduino Leonardo. Compiling the example sketch (bldc_shield_blinky_test) went fine, however, upon flashing it to the board the LED on the shield doesn't change the color (it stays white) and the following line is repeatedly printed to the Serial console:

WARNING: Board[1]; Command[901]; Answer[0]

I have initially tried the shield in its out of the box state. I have since then flashed it with the HALL version of the shield software, using the project included in the SW distribution that comes with the shield. In both cases, the shield behaved as described above when connected to the Arduino.
Does anybody know what this warning message is about?

@jsotola It behaved exactly the same before and after flashing. I assume it came pre-flashed.

what happens if you run the sketch without the BLDC shield connected to the arduino?

I never use TLE9879, but I could guess of why it doesn't work as expected.
For ATMega328p-based Arduino boards (i.e. Uno, Nano and Pro Mini), it has pin 11, 12 and 13 as SPI’s MOSI, MISO and SCLK signals, but at the same time these signals are also available on those board’s In-Circuit Serial Programming (ICSP) header pin 4, 1 and 3, except for Pro Mini which does not have a dedicated ICSP header.
This however is not the case for Arduino Leonardo and Arduino Micro which are based on ATMega32U4, for those boards, the SPI is only available on ICSP header. This is one of the reasons that some of the Arduino shields designed for Arduino Uno does not work with Arduino Leonardo when SPI communication is involved.
Based on the information of TLE9879, the SPI port is connected to pin 11-13 so it is designed to work with Arduino Uno but will not work for Arduino Leonardo.


text:
Speaker & Piezo when beeping both cause CapacitiveSense to sense
I am using this speaker:  CUI part number CSS-I4B20-SMT-TR as an alarm on a clock using atmega328 chip and Arduino IDE with the tone function. Works great.
I am also using Arduino CapacitiveSensor.h library.  Also works great.
Problem:  Want to touch the clock to put it in snooze when the alarm starts.  But when the speaker beeps, the speaker affects the Touch Sensor so it puts itself in snooze after one beep!
EMI is not the issue.  Tested with a second speaker beeping, running from a different Arduino.  Brought speaker close to the Touch Sense circuit and it DID NOT trigger. Can something be added/changed to prevent the beep pulses from affecting the rest of the circuit?

Change Speaker to Piezo Buzzer which does not have a coil.  I thought that was the answer until I read about the Piezo being a risk to the atmega328 from sending  voltage into the circuit and/or possibly drawing too much current.  I would think this could be solved using a resistor, transistor and diode.
This was tried. Piezo in circuit also was sensed when beeping.

Any thoughts would be greatly appreciated, or Options I have not thought of. Thanks.

Update:  Changed to Murata piezo sounder with circuit shown below.  Still triggers Touch Sensor when beeping.
Question:  Is there a circuit change that could reduce the effect of the speaker on the rest of the circuit?

a connect a piezo directly (200 Ohm). did you try to replace the speaker with piezo in that circuit? and I why do you use an A pin for tone()?

Yes, did test a piezo in the circuit and it does work.  I then was concerned that the piezo could somehow damage the chip, but am not sure, not familiar with risks of using a piezo.  As far as using the Analog pin, I already used the PWM pins, and the tone function does work on the analog pin.  Are there advantages to using the tone function on a PWM pin?  If so, I can change things around to make a PWM pin available. thanks

See update above.  Piezo also causes EMI problem

Turns out it is NOT and EMI problem.  Speaker is affecting the circuit which the TouchSense circuit detects.  See updated problem statement.

are they still on pins next to each other?

One speaker is on a breadboard run by an Arduino. The speaker I am concerned with is on a PCB with the touch sense circuit run by an ATMEGA328PB chip.  I held the speaker on the breadboard while beeping right next to the PCB touch sense circuit and it did not sense the beeping speaker.

A reasonable amount of EMI happens to be on the cable and not through the air, so bringing the devices close to each other is not sufficient to test for EMI.

Yes true, and in the PCB traces.  I was surprised the Piezo speaker did not work. I hoped  eliminating the speaker coil would fix it. The CapacitiveSensor circuit is very sensitive. Is there any way to suppress the EMI from the speaker?

Well I solved it with software!  I have the CapacitiveSensor only active between beeps. Works great!


text:
Writing elegant applications for Arduino
Coming from a C background, I was taught that tight loops that just burn CPU aren't desirable.
Is there any programming style guides on Arduino? Is it common practice to just let loop iterate as a tight loop forever?

Is your project powered by batteries or by mains?

@EdgarBonet mains, I'm just wondering if the loop section can be made more elegant or if its always just a tight loop, feels a little like while(1).

A microcontroller's execution path is a tight loop whether you like it or not.
If you take a CPU and connect it to empty memory the CPU will execute each empty cell in turn and loop back to the beginning of memory when it reaches the end (assuming empty memory cells equate to NOP and covers the whole memory space).
With no operating system, no scheduler, nothing except your specific code running, the CPU is always executing something.
The only time the CPU stops executing is when you manually send it to sleep to be woken by some external source (such as a timer, or a sensor sending an interrupt signal). You'd only do that, normally, to reduce power consumption.
On Arduino the loop() function is in fact executed from within a while(1) loop.
On microcontrollers when main() exits, or you call exit() it just disables interrupts and drops out to a while(1) loop.

On a multiprocess system, like your typical desktop, you usually have
way more processes than logical CPUs. When programming such systems you
therefore have to avoid burning more CPU cycles than needed. Instead,
when your program has nothing to do, it should just sleep, and leave
the CPU available for other processes.
On an Arduino, you only have one single program running at a time. It is
then not that useful to keep the CPU idle. Also, the power dissipation
is so low that you will not notice the microcontroller getting even
slightly warm. The extra complexity of getting into and out of sleep
mode is therefore not that useful. Only when running on batteries do you
care about saving every possible milliamp: then learning about sleep
modes starts getting useful.

Furthermore, with cooperative multitasking on a real mode system like an Arduino you WANT the main app loop to run as fast as possible (The tightest possible loop.) That way it checks for & responds to inputs as fast as possible. If you write interrupt code, you want THAT to finish as quickly as possible in order to get back to that tight main loop.

That is a difference between embedded systems programming and (many but not all) other types of programming. An embedded system is usually a controller of some kind and needs to be responsive to one or more kinds of events. Three typical ways of accomplishing this are

to use some kind of operating system to coordinate events and the code that manages each of them;
to write interrupt service routines (ISRs) to manage events and dispatch to code that manages them;
to poll for events frequently and dispatch to the code to manage them.

On processors as small as the AVRs, data memory and sometimes instruction memory, are scarce resources and an operating system is usually too expensive (in terms of memory needs) for most of them. On the ATtinys, forget it. On Uno, maybe kinda sorta, but memory will be a pretty severe limitation. On Megas, you might manage it.
ISR programming can be complex to write and is definitely more complex to debug(!). It's not out of the question, and it may be justified in a system that must be highly responsive - think automotive ABS braking, traction control, and fly-by-wire systems. On the other hand, systems like these have to be right.
Polling is the easiest to write and debug. You call each subsystem (code) in a tight loop (and there's your answer: "yes, let it iterate") that gives each one an opportunity to assess whether or not it needs to act and to do so. This is a case where burning cycles is inconsequential, while making a more responsive system.
In my hobbyists' classes, this is what I teach; it's also what use most. I call it "maybe-do" (and wrote about it here in answer to another question). In loop() I do nothing but call a number of functions in turn, each of which does:
   {
      if I dont need to act now,
         return;
      else {
         do what needs to be done -- quickly!;
         return;
      }
   }

thank you JRobert!


text:
how do i convert to assembly code (AVR assembly) from arduino
i have code in the Arduino ide for a temperature sensor that shows the temperature on three 7 segment displays, it shows the temperature to one decimal point. using an arduino uno. I am struggling to convert the below code to assembly. can someone please help?
#include <SevSeg.h>
#include "SevSeg.h" // Included the library for the 7 segment display
SevSeg sevseg;  // Created an object
const int sensor_pin = A0; // initialized A0 for LM35 sensor
float tempc;  //variable to store temperature in degree Celsius
float sensor_out;  // variable to store the output
unsigned long interval = 1000; // the time we need to wait
unsigned long previousMillis = 0; // millis() returns an unsigned long.
void setup() {
 pinMode(sensor_pin, INPUT);  // Declared the sensor pin as Input
 byte numDigits = 3;      it to 3.
 byte digitPins[] = {10, 11, 12};
 segment displays
 byte segmentPins[] = {9, 2, 3, 5, 6, 8, 7, 4};
 pins of displays
 bool resistorsOnSegments = true;
 bool updateWithDelaysIn = true;
 byte hardwareConfig = COMMON_CATHODE;   // Type of display we are using
 sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);
 sevseg.setBrightness(100);
 }
 void loop() {
  sensor_out = analogRead(sensor_pin);
  tempc = (sensor_out * 500) / 1024;
  tempc = tempc - 32;
 tempc = tempc * 5;
 tempc = tempc / 9;
 delay_function();
 sevseg.refreshDisplay();
}
void delay_function() {
unsigned long currentMillis = millis();
if ((unsigned long)(currentMillis - previousMillis) >= interval) {
sevseg.setNumber(tempc, 1);   // Sets temperature on display
previousMillis = millis();
}
}

It would be easier to just let the compiler do it for you.

Why would you want to? What are you going to do with the assembly code?

https://forum.arduino.cc/index.php?topic=50169.0

According to a comment in the code, you are using an LM35, which is calibrated in Celsius (10 mV/°C). Yet the code does what looks like a Fahrenheit to Celsius conversion, which would make sense with an LM34, but not with an LM35.

with the assembly code i am going to use it in atmel studio to upload it onto an arduino and run the program. i also want to see what it looks like and i am also learning assembly code.

@dirshanramlall You can upload the .hex file using atmel studio as well!


text:
How to get full response json SIM900 + Arduino?
  void toSerial(int delay_ms)
  {
    delay(delay_ms);

    while(mySerial.available())
    {
       Serial.write(mySerial.read());
    }
  }

  Serial.begin(9600);
  mySerial.begin(9600);

  mySerial.println("AT+HTTPINIT");
  toSerial(500);

  mySerial.println("AT+HTTPPARA=\"CID\", 1");
  toSerial(500);

  mySerial.println("AT+HTTPPARA=\"URL\", \"www.example.test\"");
  toSerial(500);

  mySerial.println("AT+HTTPPARA=\"CONTENT\", \"application/json\"");
  toSerial(500);

  mySerial.println("AT+HTTPACTION=0");
  toSerial(4000);

  mySerial.println("AT+HTTPREAD");
  delay(3000);

  while(mySerial.available())
  {
    Serial.write(mySerial.read());
  }

  Serial.println("");
  mySerial.println("AT+HTTPTERM");
  toSerial(500);

Result:
AT+HTTPREAD

+HTTPREAD:39
{"pinRed":0,"pinGreen":1,"pinYello

I expect messages:
{"pinRed":0,"pinGreen":1,"pinYellow":0}

Simple, reading serial data is way faster than it comes in.  So you read everything out of the buffer and cleared it so that available returned zero before everything got there.  You can check that available gives you a large enough number so that you know the whole message is there before you start reading or you can parse your message to see if it is all there before you move on.  Had you come back later and read some more on the next loop you would have seen ":0} before the next message.  It just got there after you stopped reading.

hey how did you finally make it? could you post the final code? I've been despairing of the detail for days. I would be very grateful! Greetings from Germany

Okay, I've found a solution. To start with, you need to download the server response length and loop according to the response length.


text:
Does the MKR WIFI 1010 support the arduino mouse and keyboard controller?
I am working on a project right now that needs to connect to my computer via bluetooth and access the arduino mouse and keyboard library. In my research, I've found that only the Leonardo, Due, and Micro can emulate cursor movements, but they need to have additional hardware like the HC05. I would like to keep the amount of hardware I use to a minimum, but I understand if there is no way around it. Is there any way to use the MKR WIFI 1010 like a Leonardo, or would I need to get one of the aforementioned boards and then get a bluetooth module hooked up?
PS this is my first dive into bluetooth, so any additional resources to aid me in my journey would be much appreciated.

the USB magic is in the microcontroller ... compare the boards by microcontroller

Yes, the Arduino SAMD boards are supported by the Arduino Keyboard and Mouse library.
Nano 33 IoT is a smaler alternative to MKR 1010.
But the MKR1010 or the Nano33 IoT with original NINA firmware doesn't yet support classic Bluetooth like the HC-05 module. The ArduinoBLE library and the NINA firmware support only BLE which is different.
But there is a simple way to replace the NINA firmware with the ESP32 Arduino basic Bluetooth sketch SerialToSerialBT and then use it from the SAMD. This way the NINA module will be degraded to something like a HC-05.


text:
turning positional servo motor more then 180 degrees
My RC servo motor is capable of turning more then 180 degrees(around 200 degrees) when I physically turn it, but when I use my code it only turns 180.
Is there a way to code it so that it turns to 200 instead of 180?

what code are you talking about?

First some basics to clear definitions:
A Servo Motor does not normally spin a full 360 degree rotation. Instead it is limited to a range of 180, 270 or 90 degrees depending on the make or type. A control signal is sent to the servo to position the shaft at the desired angle.

Conventional Servo Motor Timing

In a conventional analog servo motor a PWM signal with a period of 20 ms is used to control the motors. A signal of 20 ms has a frequency of 50 Hz.
The width of the pulse is varied between 1 and 2 ms to control the motor shaft position.

A pulse width of 1.5ms will cause the servo shaft to rest in the 90 degree position, the center of its travel.
A pulse width of 1ms will cause the servo shaft to rest at the 0 degree position.
A pulse width of 2ms will cause the servo shaft to rest in the 180 degree position.

Varying the pulse width between 1ms and 2ms will move the servo shaft through the full 180 degrees of its travel. You can bring it to rest at any angle you desire by adjusting the pulse width accordingly.
So if your servo is a 270 degree servo (like the domanrc DM-S0903MD or DS3218 270 Degree Digital RC Servo) the standard sweep sketch (Arduino Servo library) will let your servo sweep from 0-270 even if in the *.ino its myservo.write(180); So to simply test you could use write(map(desired_angle, 0, 270, 0, 180))
If you want to control it more precicly you use microseconds.
servo.attach(5,500,2500)
servo.writeMicroseconds(1500);

AND you have to use an extra power supply for 270 degree servos, the 5V from Arduino want make them move or only in a jittering way of.
If you just have a "defect" 180 degree servo turning to lets say 190 degree for some reason, you might try the microsecond method playing around with the values in attach, also use an extra power supply, but for real over 180 degree action get a 270 degree servo.

Just because a servo can manually be turned more than 180 degrees doesn't mean that it should be turned more than 180 degrees.
Most servos will include a certain amount of leeway in their design to help reduce damage from external forces, but the internal design will be geared1 towards operating over a 180 degree range.
While it may be possible to "overdrive" the motor by changing the PWM timing signals (see the Servo attach() reference page) doing so may end up damaging the servo itself.

1: Pun intended


text:
RGB LED color control with a single value
Apps like Photoshop have a single slider to select color: .
I'd like to achieve the same using variable resistance knob as a slider to control color of RGB LED. Can anyone put me on the right track how to linearly map color values?

Use HSV like Majenko said. But you might also like to look at adding gamma correction to those RGB values. Our eyes don't perceive differences in brightness linearly.

Any advise how to perform this? I was not going to adjust brightness or saturation and just go with max values.

Adafruit has a great explanation and guide for this at https://learn.adafruit.com/led-tricks-gamma-correction/the-issue

Thanks, gamma correction quick fix was so easy to implement and improved the look, especially after implementing pulsing fade

What you are controlling there is one out of three values from the HSV (aka HSB) colour space.
Colour can be represented in a number of different ways, called "spaces".  You computer monitor displays colour in the RGB colour space - red, green and blue. An RGB LED of course also displays in the RGB colour space.  Your colour printer works in the CMYK colour space.
Different colour spaces represent the colour using different values and combinations of values, and which colour space you use may be imposed by technical limitations (such as in the printer it is dictated by the combination of the colours of the inks).
HSV is a convenient way of visually manipulating colour since it gives you easy to understand "Hue" (the colour), "Saturation" (how much colour) and "Value" (or "Brightness" - how light the colour is) values that are easy for a human to understand.
However physical devices don't generally work with that colour space, so you need to be able to translate between them.
You can think of HSV as the "Human" colour space, and RGB as the "Digital" colour space.
Fortunately it's relatively simple to convert from one to another and there are a number of code snippets online that give examples of how to do it.
I'm going to include one here that I use in my chipKIT TFT display library "Cariad".  Given three 8 bit values (0-255) of "hue" "sat" and "val" it will calculate the red, green and blue values. "hue" would be the one you change with your pot - the others can be static values (or you could add more pots to control those too).
    unsigned int H_accent = hue/43;
    unsigned int bottom = ((255 - sat) * val)>>8;
    unsigned int top = val;
    unsigned char rising  = ((top-bottom)  *(hue%43   )  )  /  43  +  bottom;
    unsigned char falling = ((top-bottom)  *(43-hue%43)  )  /  43  +  bottom;

    int r = 0;
    int g = 0;
    int b = 0;

    switch(H_accent) {
        case 0:
                r = top;
                g = rising;
                b = bottom;
        break;

        case 1:
                r = falling;
                g = top;
                b = bottom;
        break;

        case 2:
                r = bottom;
                g = top;
                b = rising;
        break;

        case 3:
                r = bottom;
                g = falling;
                b = top;
        break;

        case 4:
                r = rising;
                g = bottom;
                b = top;
        break;

        case 5:
                r = top;
                g = bottom;
                b = falling;
        break;
    }
    if (r > 255) r = 255;
    if (g > 255) g = 255;
    if (b > 255) b = 255;
    if (r < 0) r = 0;
    if (g < 0) g = 0;
    if (b < 0) b = 0;

What are the ranges for "hue" "sat" and "val" values in this script? Is it 0-128?

0-255 full 8 bit range

Works like a charm. I wander why colors look different while Arduino board is powered via USB and via power supply connection

Because of the varying forward voltages of the three LEDs and the differing incoming supply voltage.


text:
How to replace String objects with char arrays while still using string methods
I am running the following code on my ESP8266 (AI-Thinker ESP8266MOD).
I send an HTTP GET request and a pin is set to high for a 1/2 second.
However, after some time (sometimes 1hr, 2hrs, 12hrs, totally random), it stops responding to HTTP requests.
I think it might be because of heap fragmentation due to the String objects I'm using.
Questions:
How can I replace the request (in loop()) and s and text (in GenerateResponse()) objects with  char arrays?
After I replace the String objects with char arrays, how can I use the indexOf() method and + operator on the char arrays?
Will this approach help with heap fragmentation?
Is it possible to find out if heap fragmentation is the problem?
#include <ESP8266WiFi.h>

const char* ssid = "myWifi";
const char* wifiPassword = "y76ggS";
const char* passwordToOpenDoor = "/81"; //password should begin with a slash

const int doorPin = 5;

WiFiServer server(301); //Pick any port number you like
WiFiClient client;

void setup() {
  Serial.begin(115200);
  delay(10);
  Serial.println(WiFi.localIP());

  pinMode(doorPin, OUTPUT);
  digitalWrite(doorPin, 0);

  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, wifiPassword);

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

  server.begin();
  Serial.println("Server started. Diagnostics info:");
  Serial.println(WiFi.localIP());
}

void loop() {
  client = server.available();
  if (!client) {
    return;
  }

  while(!client.available()){
    delay(1);
  }

  String request = client.readStringUntil('\r');
  client.flush();

  Serial.println(request);
  if (request.indexOf(passwordToOpenDoor) != -1) { //Is password correct?
    GenerateResponse("Password is correct");
    OpenDoor();
  }
  //Got a GET request and it wasn't the favicon.ico request, must have been a bad password:
  else if (request.indexOf("favicon.ico") == -1) {
    GenerateResponse("Password is incorrect.");
  }
}

void OpenDoor() {
  digitalWrite(doorPin, 1);
  delay(500);
  digitalWrite(doorPin, 0);
}

void GenerateResponse(String text) {
  Serial.println(text);
  String s = "HTTP/1.1 200 OK\r\n";
  s += "Content-Type: text/html\r\n\r\n";
  s += "<!DOCTYPE HTML>\r\n\r\n";
  s += "

" + text + "
";
  s += "\n";
  client.flush();
  client.print(s);
  delay(1);
}

Further to all the answers provided so far, when using char array, String.indexOf() can be replaced by strstr(str1, str2). It return position number when str2 match part of the str1.

For learning, read ` that have all the function for c string and array manipulation that you need when handling char array.

@hcheung on this line "else if (strstr(request, "favicon.ico") == -1) {" I get "ISO C++ forbids comparison between pointer and integer [-fpermissive]"

I had to remove the comparison with 1 and -1 in both if statements to get it to compile.

You already received good answer about some general ideas for
replacing String objects with C strings. Here I will try to add some
more tricks more specifically targeted to your actual situation.
I can see two places in your program where the use of String shines by
its convenience, and replacing it with C strings will require some
effort. The first is the use of Stream::readStringUntil(char) for
getting the first request line. Here
I see no better option (see edit below) than reading
the stream one character at a time, and putting those characters into an
array:
const size_t input_buffer_length = 256;

// Read a line of text up to the first '\r'.
// Returns a NUL-terminated string, without the final '\r',
// into a statically allocated buffer.
// Warning: this never times out.
const char *readline(Stream &input)
{
  static char buffer[input_buffer_length];
  size_t pos = 0;  // writing position within the buffer
  int c;           // current character
  while ((c = input.read()) != '\r') {
    if (c >= 0 && pos < sizeof buffer - 1) {
      buffer[pos++] = c;
    }
  }
  buffer[pos] = '\0';  // terminate the string
  return buffer;
}

You would use it like this:
const char *request = readline(client);

For more robustness, you may want to add a timeout. Note also that this
implementation is no reentrant, as it uses a static buffer. This is not
an issue for your use case.
Edit: As noted by hcheung in a comment, you do not need to implement
this readline() function, as you can use
Stream::readBytesUntil(), which handles the timeout
and is provided by the Arduino core:
char buffer[input_buffer_length];
client.readBytesUntil('\r', buffer, input_buffer_length);

The other place is the usage of String::operator+=(const char *) for
generating the response. Here I would advice you against using
strcat() or strncat(): these will require extra memory to store the
concatenated string which you probably do not need. Instead, you can
simply print() the pieces one by one:
void GenerateResponse(const char *text) {
  Serial.println(text);
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println();
  client.println("<!DOCTYPE HTML>");
  client.println("");
  client.print("

");
  client.print(text);
  client.println("
");
  client.flush();
  delay(1);
}

Alternatively, you can make use of the implicit concatenation of string
literals in order to reduce the number of calls to client.print():
void GenerateResponse(const char *text) {
  Serial.println(text);
  client.print(
      "HTTP/1.1 200 OK\r\n"
      "Content-Type: text/html\r\n"
      "\r\n"
      "<!DOCTYPE HTML>\r\n"
      "\r\n"
      "

"
  );
  client.print(text);
  client.print("
\r\n");
  client.flush();
  delay(1);
}

Instead of creating a customised readline() function, it probably cleaner to use client.readBytesUntil('\r', buffer, length) since both readStringUntil() and readBytesUntil() are all inherited from Stream class.

Thanks for your answer. It's been running now for over 12 hrs :) Looks like the String objects were the issue. I'll let you know if it's still working after a couple of days.

So here is code to get you started:
myMessageArray [256] = {'\0'}; // Define global array large enough and zero terminate

the + method is replaced by
strcpy (myMessageArray, "Text to Add");
// Initializes the myMessageArray starts at index 0
strcat (myMessageArray, "More text to Add");
// Appends to the myMessageArray starts at current index

converting numeric values to chars:
uint_16_t myNumberValue  = 31253;
char numBuffer [16] = {'\0'}; // Helper buffer for conversions

itoa (myNumberValue,numBuffer,10);  // converts an integer to a base 10 (decimal) char
itoa (myNumberValue,numBuffer,2);  // converts an integer to a base 2 (binary) char
itoa (myNuberValue,numBuffer,16);  // converts an integer to a base 16 (hex) char

itoa initilizes a char array so we need the helper array:
strcat (myMessageArray, numBuffer);

to convert float we use
dtostrf(floatVariable, StringLengthIncDecimalPoint, numVarsAfterDecimal, numBuffer);

to convert chars back to int use
int16_t myIntVar = atoi(numBuffer);

to convert chars back to floats use
float myFloatVar = atof(numBuffer, decimalsToShow); // using just atof(numBuffer)
gives you standard x.XX only 2 decimals

A working IndexOf for char arrays:
/*******************************************************************************/
/**
    \brief Finds the index of the given value in the array starting at the given index
    \author codebreaker007
    \param [in] targetArray the array to search through for the char
    \param [in] valueToFind the value to find
    \param [in] startIndex the index to start searching at
    \return the index of the value within the array

    \details This method returns INDEX_NOT_FOUND^(-1) for a null input array.
        A negative startIndex is treated as zero. A startIndex larger than the array
        length will return INDEX_NOT_FOUND(-1)
*/
/********************************************************************************/
int8_t indexOf(char* targetArray, char valueToFind, uint16_t startIndex = 0) {
  if (targetArray == NULL) {
    return INDEX_NOT_FOUND;
  }
  if (startIndex <= 0) {
    startIndex = 0;
  }
  for (uint16_t i = startIndex; i < strlen(targetArray); i++) {
    if (valueToFind == targetArray[i]) {
      return i;
    }
  }
  return INDEX_NOT_FOUND;
}

To compare char arrays you should look into the strcmp function and if you want to checkthe first n char tomatchyou use:
if (strncmp(myMessageArray , "POST", 4 ) == 0) {
// compares the first 4 chars if it matches = 0, see details in the arduino doku

Hope this comprehensive intro to char arrays helps you for your current and future projects. How to find out - convert to char arrays and if its runnibg stable that was it. Before that conversion you can never rule out String class as culprit.

Nice thorough answer. (Voted). I tend to use sprintf() and printf() in C, which is too heavy-weight for most Arduino boards. I am also not sure about the WiFiClient and WiFiServer classes and whether they have methods that return char arrays rather than strings.

This way is perfect to have buffer overflows. I propose to use snprintf function.

All the standard classes on ESP8366/32 use char (after learning the String heap problem in com heavy szenarios)  As snprintf and similar all use temporary char arrays - look into the sources - this delays the problem of heap fragmentation, but is not solving it @SBF where do you see buffer overflows I propose global char arrayscompiled to flash - I have esps running for 1.5 years now with heavy use of char arrays not a single reset/crash - same program with String-class crashes after 30+ mins

Re “A working IndexOf for char arrays”: or just use the good old strchr().

@Codebreaker007: I totally agree to avoid Sting class and use char buffer, however, if your buffer is too small when you strcat you have a buffer overflow. snprintf() has an argument to limit the maximum number of bytes to be used in the buffer. The generated string has a length of at most n-1, leaving space for the additional terminating null character.

@SBF: snprintf() is probably a little bit overkill for concatenating strings. A smaller overflow-safe alternative to strcat() is strncat().

Sure, but it replaces all the itoa fuzz too. With strncat() you need to calculate the remaining free bytes in the buffer.

You asked: "After I replace the String objects with char arrays, how can I use the indexOf() method and + operator on the char arrays?"
Short answer: You can't. If you want to use C strings (aka arrays of char), you'll have to use C string functions.
The String methods operate on String objects. The common wisdom is to avoid the String class entirely since it relies on heap memory, and Arduinos are far, far too memory-starved to be able to use a class like String which creates temporary objects on the heap.


text:
Read status on SCART output
I'm trying to get the status of my set top box (on/off).
It does have USB but it's always powered on.
It has optical out that is also always on.
It has an IP address that always responds to ping.
So my next idea is to read the signal in the SCART.
If I read the voltage across pin 8 and 14 I get 0-ish when off and 12 when on.
But when it powers on it spikes at 18 volt (at least what my multimeter can see).
https://youtu.be/D2eVFe33MeM
What do I need to do to read this?
If I add a voltage divider with 1 and 4.7 Kohm I get a safe voltage if it does not go above 18 volt at any time.
But what can I do to be sure I don't burn a ESP chip?
Is there any way to make sure it's safe to read even if it spikes at say 25 volts?

This is really a question best asked in https://electronics.stackexchange.com/.  But you could add a series limiting resistor then back to back zener diodes to ground to control any voltage spikes.  Suppose you could get away w/only one zener.  But most suppression circuits use two.

An optical isolator with appropriate resistors would be my recommendation.

I would use something like below. The optical isolator (PC817 or similar) protects your ESP.

Use a 1.0-1.5K resistor from the incoming SCART switch signal (SCART pin 8) to the anode of the Opto isolator (pin 1 in case of the PC817). This will limit the current through the PC817 internal LED to about 10mA with a 12V signal but the PC817 can survive up to 50mA, i.e. up to 60V on the SCART plug and even then will not damage your ESP processor.

Connect SCART ground (pin 14) to the cathode of the Opto isolator
(pin 2).

Connect a 3.3K - 4.7K resistor to the collector of the phototransistor of the PC817 (pin 4 of the PC817) and connect the other side of this resistor to Vcc of your ESP (+3.3V) as a pullup.

Connect pin 3 (emitter) of the PC817 to the Ground of your ESP.

Connect a digital input pin of your ESP to pin 4 (phototransistor collector) of your PC817 to create an active-low signal indicating your set top box is active.

This is the schematic you could use:

simulate this circuit – Schematic created using CircuitLab

I can't find a opto isolator locally. I can order one, but the shipping is about 40 times higher than the unit price. So I did some testing and with a simple LED and a resistor. The LED turns on and off as it should. Sadly the phototransistor I have can't see that light. But I just need to find the correct combination and it will work. Thank you for the idea and schematic. But sadly due to shipping cost I can't build it like that, I will be DIY-ing one.


text:
Bootloader onto an ATmega328p (3.3V/8MHz), the dude won't finish his business
Hi and thank you reading my question !
I need for my projects to design as small as i can. Both the skills, and the hardware counts. So i can't use a DIP package for them, and i have gone for a TQFP package. The point is to programm a TQFP ATmega328P using an external board without soldering it, which plugs into a Arduino UNO. Like that no need to constantly check the connection and everything. The shield is a basically a fat Arduino Pro Mini, with all the options available (3.3V/5V, 8MHz/16MHz, Sparkfun FTDI can be connected, ...) as shown below :

As you can see I am the enginneer of Gymetrics, but not an electronic enginner nor a programmer ... I actually did some mistakes designing it with the SS pin pins connected together and not the one of the Arduino UNO to the reset pin of the target, and added a capacitor in the wrong place. I did manage to connect the pin 10 of the Arduino to the reset pin of the target on another shield and take out that capacitor. When you order one you got tens of them at the minimum ...
As the schematic is the same as the Mini, and i don't think it's needed. I know that burn in sockets already exists, but because you to reverse enginneer the pins to make it works, i prefered design my own. Ok sorry for that long introduction, but i prefered you to know the full reflexion. As you imagine, i've been searching on so many forum, tutoriels, and so ever to do it and still it doesn't work.
As it is the first time i burn a bootloader into an ATmega328P, i am not confident in what i am doing. So i tried to burn a bootloader into an Arduino Pro Mini, it works fine. I'm happy on a point : I know how to follow a step by step procedure !
The microcontroller i use (ATmega328P) is the same as the one on the Arduino Pro Mini, so the configuration in the Arduino IDE is the same. However, when the work is done easily with the Arduino Pro Mini, it doesn't work with my board. Here is what the IDE errors shows :
Arduino : 1.8.12 (Windows 10), Carte : "Arduino Pro or Pro Mini, ATmega328P (3.3V, 8 MHz)"

C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avrdude -CC:\Program Files
(x86)\Arduino\hardware\tools\avr/etc/avrdude.conf -v -patmega328p -cstk500v1 -PCOM7 -b19200 -e -
Ulock:w:0x3F:m -Uefuse:w:0xFD:m -Uhfuse:w:0xDA:m -Ulfuse:w:0xFF:m

 avrdude: Version 6.3-20190619
     Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
     Copyright (c) 2007-2014 Joerg Wunsch

     System wide configuration file is "C:\Program Files
 (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf"

     Using Port                    : COM7
     Using Programmer              : stk500v1
     Overriding Baud Rate          : 19200
     AVR Part                      : ATmega328P
     Chip Erase delay              : 9000 us
     PAGEL                         : PD7
     BS2                           : PC2
     RESET disposition             : dedicated
     RETRY pulse                   : SCK
     serial program mode           : yes
     parallel program mode         : yes
     Timeout                       : 200
     StabDelay                     : 100
     CmdexeDelay                   : 25
     SyncLoops                     : 32
     ByteDelay                     : 0
     PollIndex                     : 3
     PollValue                     : 0x53
     Memory Detail                 :

                              Block Poll               Page                       Polled
       Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
       ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
       eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
       flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
       lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
       hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
       efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
       lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
       calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
       signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

     Programmer Type : STK500
     Description     : Atmel STK500 Version 1.x firmware
     Hardware Version: 2
     Firmware Version: 1.18
     Topcard         : Unknown
     Vtarget         : 0.0 V
     Varef           : 0.0 V
     Oscillator      : Off
     SCK period      : 0.1 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.02s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: erasing chip
avrdude: reading input file "0x3F"
avrdude: writing lock (1 bytes):

Writing | ################################################## | 100% 0.01s

avrdude: 1 bytes of lock written
avrdude: verifying lock memory against 0x3F:
avrdude: load data lock data from input file 0x3F:
avrdude: input file 0x3F contains 1 bytes
avrdude: reading on-chip lock data:

Reading | ################################################## | 100% 0.01s

avrdude: verifying ...
avrdude: 1 bytes of lock verified
avrdude: reading input file "0xFD"
avrdude: writing efuse (1 bytes):

Writing | ################################################## | 100% 0.02s

avrdude: 1 bytes of efuse written
avrdude: verifying efuse memory against 0xFD:
avrdude: load data efuse data from input file 0xFD:
avrdude: input file 0xFD contains 1 bytes
avrdude: reading on-chip efuse data:

Reading | ################################################## | 100% 0.01s

avrdude: verifying ...
avrdude: 1 bytes of efuse verified
avrdude: reading input file "0xDA"
avrdude: writing hfuse (1 bytes):

C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avrdude -CC:\Program Files         (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf -v -patmega328p -cstk500v1 -PCOM7 -b19200 -    Uflash:w:C:\Program Files     (x86)\Arduino\hardware\arduino\avr/bootloaders/atmega/ATmegaBOOT_168_atmega328_pro_8MHz.hex:i -    Ulock:w:0x0F:m
Writing | ################################################## | 100% 0.02s

avrdude: 1 bytes of hfuse written
avrdude: verifying hfuse memory against 0xDA:
avrdude: load data hfuse data from input file 0xDA:
avrdude: input file 0xDA contains 1 bytes
avrdude: reading on-chip hfuse data:

Reading | ################################################## | 100% 0.01s

avrdude: verifying ...
avrdude: 1 bytes of hfuse verified
avrdude: reading input file "0xFF"
avrdude: writing lfuse (1 bytes):

Writing | ################################################## | 100% 0.03s

avrdude: 1 bytes of lfuse written
avrdude: verifying lfuse memory against 0xFF:
avrdude: load data lfuse data from input file 0xFF:
avrdude: input file 0xFF contains 1 bytes
avrdude: reading on-chip lfuse data:

Reading | ################################################## | 100% 0.01s

avrdude: verifying ...
avrdude: 1 bytes of lfuse verified

avrdude done.  Thank you.

avrdude: Version 6.3-20190619
     Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
     Copyright (c) 2007-2014 Joerg Wunsch

     System wide configuration file is "C:\Program Files     (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf"

     Using Port                    : COM7
     Using Programmer              : stk500v1
     Overriding Baud Rate          : 19200
     AVR Part                      : ATmega328P
     Chip Erase delay              : 9000 us
     PAGEL                         : PD7
     BS2                           : PC2
     RESET disposition             : dedicated
     RETRY pulse                   : SCK
     serial program mode           : yes
     parallel program mode         : yes
     Timeout                       : 200
     StabDelay                     : 100
     CmdexeDelay                   : 25
     SyncLoops                     : 32
     ByteDelay                     : 0
     PollIndex                     : 3
     PollValue                     : 0x53
     Memory Detail                 :

                              Block Poll               Page                       Polled
       Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
       ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
       eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
       flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
       lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
       hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
       efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
       lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
       calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
       signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

     Programmer Type : STK500
     Description     : Atmel STK500 Version 1.x firmware
     Hardware Version: 2
     Firmware Version: 1.18
     Topcard         : Unknown
     Vtarget         : 0.0 V
     Varef           : 0.0 V
     Oscillator      : Off
     SCK period      : 0.1 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.02s

avrdude: Device signature = 0x000000 (retrying)

Reading | ################################################## | 100% 0.02s

avrdude: Device signature = 0x000000 (retrying)

Erreur lors de la gravure de la séquence d'initialisation.
Reading | ################################################## | 100% 0.02s

avrdude: Device signature = 0x000000
avrdude: Yikes!  Invalid device signature.
     Double check connections and try again, or use -F to override
     this check.

avrdude done.  Thank you.

Something very weird is that it reads the first and second time the right signature, and it's what i understand reading the error, and then doesn't read the signature anymore. If i try to burn again the bootloader, it can't read the signature anymore. I don't know what i am missing here.
What should i do ? I'm gonna try soldering an ATmega328P directly to see if it's a problem in the socket, but i don't think it is as it is working in the first communications.
Thank you !
EDIT
Programming interface :
UNO               Target

10                RST
11                MOSI
12                MISO
13                SCK

What is your programming interface connections? Pro Mini often need the DTR pin for programming.

I do not use the DTR pin on the Pro Mini to burn the bootloader. I directly plug the reset of the pro mini (target) to the pin 10 of the UNO.

Just give it a try. DTR ensure there is a short single pulse while the timing for reset may not work, plus it could have the multiple bouncing effect. When I programming Pro Mini, reset never works while DTR will.

With the DTR pin instead of the reset pin, i get a wrong device signature changing every time, but better than nothing. It never reads 0x000000 anymore, but some random bytes : 0x0000FF or 0x000007 or 0x00FF00

The first time the fuses are still in the factory default settings. That is; internal oscillator. After setting the fuses to the values you specifies, the chip uses the external crystal. The fact that you don't get a response could indicate a problem with the crystal (or it's loading capacitors). Looking at your board it seem like you added the option to change crystals by moving jumpers. However in the picture there are no jumpers present.

I use the jumpers, but not for you to get confused with them seeing the picture, i removed all of them. I have jumpers on both sides of the 8MHz crystal as i am writting this message. So you think i should try to program it without crystals ? and you the internal one ?

The loading capacitors are 22uF, following the datasheet recommandation and the Pro Mini schematic.

It certainly does look like it's unable to clock after setting the fuses. I would suggest that crystal circuits are very sensitive and maybe the jumpers themselves are interfering with it. You could try bridging the jumpers with solder (in the underside) to bypass them. Also using an oscilloscope with the probe set to 10X to test if the crystal is actually oscillating will help.

Ok so i don't have a working 10X probe nor a 100X probe, somehow it's broken. I'm going blind on this one sorry. I think you right on that point where jumpers may interfer with the crystal. I did solder to the 8MHz crystal, because this is the one i ll mostly use in the future for power consumption. The result is that it still doesn't work with the 4 uC i use. Will try with another one, one i never touched, but not so much hope on that point.

@HugoVernier-Lambert 22uF, did you really mean that?

@Wirewrap aïe ... Thank you, I think this might be the problem. I did the full schematic back again and i wanted to put 22pF but did put 22uF ... well i go change it and see if the magic happens ! Thank you again for pointing that out !

Problem solved, i did put two capacitors way to big on the XTAL's pins, which was making the crystal unable to resonate.
Thanks to @Wirewrap for finding the mistake


text:
What is the baud rate for Wiegand?
I am attempting to develop an Arduino project that can identify the bit format of a card (26-bit being the most common but not the only one).
This a library sets the serial to be 9600 baud.
https://github.com/paulo-raca/YetAnotherArduinoWiegandLibrary
This documentation says the data bit width is about 100us and the "inter pulse" or the time between the data bit is 20-100us.
https://docs.tibbo.com/taiko/ser_wiegand_mode
I don't understand how these match up? Also, Wiegand isn't even really serial. It uses two inputs - One input is for the on bits and another input is for the off bits.

The library does never use anything regarding Serial. The examples use Serial as interaction way, to show the results to the user. Bit that has nothing to do with the Wiegand RFID reader

Wiegand doesn't have a baud rate as such. It's an edge-based input protocol where it looks for HIGH to LOW transitions on two different input lines.
There are certain timing requirements, in that you can't send data faster than the receiver is capable of receiving and pulses have to be wide enough for the receiver to read, and there is a minimum time for the gap between messages, but other than that there is no defined baud rate.

Just tested my HID multiCLASS SE RP40 920P with an oscilloscope.
Time between pulses: ~ 2 ms

Pulse duration: ~ 40 us

Measured a few different events, they seemed very consistent.


text:
Use NeoSWSerial instead of SoftwareSerial with Adafruit Fingerprint Library
I'm using the FPM10A fingerprint sensor together with the Adafruit Fingerprint Library. I also have a GPS and Bluetooth module on the board already (connected to an Arduino UNO) and I'm using the neoSWserial library to communicate with them. I would like to use neoSWserial to communicate with the fingerprint sensor.
I've replaced all the instances of SoftwareSerial with NeoSWSerial in the respective .h and .cpp files but now the program says
'Did not find fingerprint sensor'

For completeness here's the sketch, .h and .cpp file:
/***************************************************
  This is an example sketch for our optical Fingerprint sensor

  Designed specifically to work with the Adafruit BMP085 Breakout
  ----> http://www.adafruit.com/products/751

  These displays use TTL Serial to communicate, 2 pins are required to
  interface
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ****************************************************/

#include <Adafruit_Fingerprint.h>

// On Leonardo/Micro or others with hardware serial, use those! #0 is green wire, #1 is white
// uncomment this line:
// #define mySerial Serial1

// For UNO and others without hardware serial, we must use software serial...
// pin #2 is IN from sensor (GREEN wire)
// pin #3 is OUT from arduino  (WHITE wire)
// comment these two lines if using hardware serial
NeoSWSerial mySerial(12, 13);

Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);

void setup()
{
  Serial.begin(9600);
  while (!Serial);  // For Yun/Leo/Micro/Zero/...
  delay(100);
  Serial.println("\n\nAdafruit finger detect test");

  // set the data rate for the sensor serial port
  finger.begin(57600);
  delay(5);
  if (finger.verifyPassword()) {
    Serial.println("Found fingerprint sensor!");
  } else {
    Serial.println("Did not find fingerprint sensor :(");
    while (1) { delay(1); }
  }

  finger.getTemplateCount();
  Serial.print("Sensor contains "); Serial.print(finger.templateCount); Serial.println(" templates");
  Serial.println("Waiting for valid finger...");
}

void loop()                     // run over and over again
{
  getFingerprintIDez();
  delay(50);            //don't ned to run this at full speed.
}

uint8_t getFingerprintID() {
  uint8_t p = finger.getImage();
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image taken");
      break;
    case FINGERPRINT_NOFINGER:
      Serial.println("No finger detected");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_IMAGEFAIL:
      Serial.println("Imaging error");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }

  // OK success!

  p = finger.image2Tz();
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image converted");
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.println("Image too messy");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println("Could not find fingerprint features");
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println("Could not find fingerprint features");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }

  // OK converted!
  p = finger.fingerFastSearch();
  if (p == FINGERPRINT_OK) {
    Serial.println("Found a print match!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("Communication error");
    return p;
  } else if (p == FINGERPRINT_NOTFOUND) {
    Serial.println("Did not find a match");
    return p;
  } else {
    Serial.println("Unknown error");
    return p;
  }

  // found a match!
  Serial.print("Found ID #"); Serial.print(finger.fingerID);
  Serial.print(" with confidence of "); Serial.println(finger.confidence);

  return finger.fingerID;
}

// returns -1 if failed, otherwise returns ID #
int getFingerprintIDez() {
  uint8_t p = finger.getImage();
  if (p != FINGERPRINT_OK)  return -1;

  p = finger.image2Tz();
  if (p != FINGERPRINT_OK)  return -1;

  p = finger.fingerFastSearch();
  if (p != FINGERPRINT_OK)  return -1;

  // found a match!
  Serial.print("Found ID #"); Serial.print(finger.fingerID);
  Serial.print(" with confidence of "); Serial.println(finger.confidence);
  return finger.fingerID;
}

The header file:
#ifndef ADAFRUIT_FINGERPRINT_H
#define ADAFRUIT_FINGERPRINT_H

/***************************************************
  This is a library for our optical Fingerprint sensor

  Designed specifically to work with the Adafruit Fingerprint sensor
  ----> http://www.adafruit.com/products/751

  These displays use TTL Serial to communicate, 2 pins are required to
  interface
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ****************************************************/

#include "Arduino.h"
#if defined(__AVR__) || defined(ESP8266)
#include <NeoSWSerial.h>
#elif defined(FREEDOM_E300_HIFIVE1)
#include <NeoSWSerial.h>
#define NeoSWSerial NeoSWSerial
#endif

#define FINGERPRINT_OK 0x00
#define FINGERPRINT_PACKETRECIEVEERR 0x01
#define FINGERPRINT_NOFINGER 0x02
#define FINGERPRINT_IMAGEFAIL 0x03
#define FINGERPRINT_IMAGEMESS 0x06
#define FINGERPRINT_FEATUREFAIL 0x07
#define FINGERPRINT_NOMATCH 0x08
#define FINGERPRINT_NOTFOUND 0x09
#define FINGERPRINT_ENROLLMISMATCH 0x0A
#define FINGERPRINT_BADLOCATION 0x0B
#define FINGERPRINT_DBRANGEFAIL 0x0C
#define FINGERPRINT_UPLOADFEATUREFAIL 0x0D
#define FINGERPRINT_PACKETRESPONSEFAIL 0x0E
#define FINGERPRINT_UPLOADFAIL 0x0F
#define FINGERPRINT_DELETEFAIL 0x10
#define FINGERPRINT_DBCLEARFAIL 0x11
#define FINGERPRINT_PASSFAIL 0x13
#define FINGERPRINT_INVALIDIMAGE 0x15
#define FINGERPRINT_FLASHERR 0x18
#define FINGERPRINT_INVALIDREG 0x1A
#define FINGERPRINT_ADDRCODE 0x20
#define FINGERPRINT_PASSVERIFY 0x21

#define FINGERPRINT_STARTCODE 0xEF01

#define FINGERPRINT_COMMANDPACKET 0x1
#define FINGERPRINT_DATAPACKET 0x2
#define FINGERPRINT_ACKPACKET 0x7
#define FINGERPRINT_ENDDATAPACKET 0x8

#define FINGERPRINT_TIMEOUT 0xFF
#define FINGERPRINT_BADPACKET 0xFE

#define FINGERPRINT_GETIMAGE 0x01
#define FINGERPRINT_IMAGE2TZ 0x02
#define FINGERPRINT_REGMODEL 0x05
#define FINGERPRINT_STORE 0x06
#define FINGERPRINT_LOAD 0x07
#define FINGERPRINT_UPLOAD 0x08
#define FINGERPRINT_DELETE 0x0C
#define FINGERPRINT_EMPTY 0x0D
#define FINGERPRINT_SETPASSWORD 0x12
#define FINGERPRINT_VERIFYPASSWORD 0x13
#define FINGERPRINT_HISPEEDSEARCH 0x1B
#define FINGERPRINT_TEMPLATECOUNT 0x1D

//#define FINGERPRINT_DEBUG

#define DEFAULTTIMEOUT 1000 ///< UART reading timeout in milliseconds

///! Helper class to craft UART packets
struct Adafruit_Fingerprint_Packet {

  /**************************************************************************/
  /*!
      @brief   Create a new UART-borne packet
      @param   type Command, data, ack type packet
      @param   length Size of payload
      @param   data Pointer to bytes of size length we will memcopy into the
     internal buffer
  */
  /**************************************************************************/

  Adafruit_Fingerprint_Packet(uint8_t type, uint16_t length, uint8_t *data) {
    this->start_code = FINGERPRINT_STARTCODE;
    this->type = type;
    this->length = length;
    address[0] = 0xFF;
    address[1] = 0xFF;
    address[2] = 0xFF;
    address[3] = 0xFF;
    if (length < 64)
      memcpy(this->data, data, length);
    else
      memcpy(this->data, data, 64);
  }
  uint16_t start_code; ///< "Wakeup" code for packet detection
  uint8_t address[4];  ///< 32-bit Fingerprint sensor address
  uint8_t type;        ///< Type of packet
  uint16_t length;     ///< Length of packet
  uint8_t data[64];    ///< The raw buffer for packet payload
};

///! Helper class to communicate with and keep state for fingerprint sensors
class Adafruit_Fingerprint {
public:
#if defined(__AVR__) || defined(ESP8266) || defined(FREEDOM_E300_HIFIVE1)
  Adafruit_Fingerprint(NeoSWSerial *ss, uint32_t password = 0x0);
#endif
  Adafruit_Fingerprint(HardwareSerial *hs, uint32_t password = 0x0);

  void begin(uint32_t baud);

  boolean verifyPassword(void);
  uint8_t getImage(void);
  uint8_t image2Tz(uint8_t slot = 1);
  uint8_t createModel(void);

  uint8_t emptyDatabase(void);
  uint8_t storeModel(uint16_t id);
  uint8_t loadModel(uint16_t id);
  uint8_t getModel(void);
  uint8_t deleteModel(uint16_t id);
  uint8_t fingerFastSearch(void);
  uint8_t getTemplateCount(void);
  uint8_t setPassword(uint32_t password);
  void writeStructuredPacket(const Adafruit_Fingerprint_Packet &p);
  uint8_t getStructuredPacket(Adafruit_Fingerprint_Packet *p,
                              uint16_t timeout = DEFAULTTIMEOUT);

  /// The matching location that is set by fingerFastSearch()
  uint16_t fingerID;
  /// The confidence of the fingerFastSearch() match, higher numbers are more
  /// confidents
  uint16_t confidence;
  /// The number of stored templates in the sensor, set by getTemplateCount()
  uint16_t templateCount;

private:
  uint8_t checkPassword(void);
  uint32_t thePassword;
  uint32_t theAddress;
  uint8_t recvPacket[20];

  Stream *mySerial;
#if defined(__AVR__) || defined(ESP8266) || defined(FREEDOM_E300_HIFIVE1)
  NeoSWSerial *swSerial;
#endif
  HardwareSerial *hwSerial;
};

#endif

And the .cpp file:
/***************************************************
  This is a library for our optical Fingerprint sensor

  Designed specifically to work with the Adafruit Fingerprint sensor
  ----> http://www.adafruit.com/products/751

  These displays use TTL Serial to communicate, 2 pins are required to
  interface
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ****************************************************/

#include "Adafruit_Fingerprint.h"

//#define FINGERPRINT_DEBUG

#if ARDUINO >= 100
#define SERIAL_WRITE(...) mySerial->write(__VA_ARGS__)
#else
#define SERIAL_WRITE(...) mySerial->write(__VA_ARGS__, BYTE)
#endif

#define SERIAL_WRITE_U16(v)                                                    \
  SERIAL_WRITE((uint8_t)(v >> 8));                                             \
  SERIAL_WRITE((uint8_t)(v & 0xFF));

#define GET_CMD_PACKET(...)                                                    \
  uint8_t data[] = {__VA_ARGS__};                                              \
  Adafruit_Fingerprint_Packet packet(FINGERPRINT_COMMANDPACKET, sizeof(data),  \
                                     data);                                    \
  writeStructuredPacket(packet);                                               \
  if (getStructuredPacket(&packet) != FINGERPRINT_OK)                          \
    return FINGERPRINT_PACKETRECIEVEERR;                                       \
  if (packet.type != FINGERPRINT_ACKPACKET)                                    \
    return FINGERPRINT_PACKETRECIEVEERR;

#define SEND_CMD_PACKET(...)                                                   \
  GET_CMD_PACKET(__VA_ARGS__);                                                 \
  return packet.data[0];

/***************************************************************************
 PUBLIC FUNCTIONS
 ***************************************************************************/

#if defined(__AVR__) || defined(ESP8266) || defined(FREEDOM_E300_HIFIVE1)
/**************************************************************************/
/*!
    @brief  Instantiates sensor with Software Serial
    @param  ss Pointer to NeoSWSerial object
    @param  password 32-bit integer password (default is 0)
*/
/**************************************************************************/
Adafruit_Fingerprint::Adafruit_Fingerprint(NeoSWSerial *ss,
                                           uint32_t password) {
  thePassword = password;
  theAddress = 0xFFFFFFFF;

  hwSerial = NULL;
  swSerial = ss;
  mySerial = swSerial;
}
#endif

/**************************************************************************/
/*!
    @brief  Instantiates sensor with Hardware Serial
    @param  hs Pointer to HardwareSerial object
    @param  password 32-bit integer password (default is 0)

*/
/**************************************************************************/
Adafruit_Fingerprint::Adafruit_Fingerprint(HardwareSerial *hs,
                                           uint32_t password) {
  thePassword = password;
  theAddress = 0xFFFFFFFF;

#if defined(__AVR__) || defined(ESP8266) || defined(FREEDOM_E300_HIFIVE1)
  swSerial = NULL;
#endif
  hwSerial = hs;
  mySerial = hwSerial;
}

/**************************************************************************/
/*!
    @brief  Initializes serial interface and baud rate
    @param  baudrate Sensor's UART baud rate (usually 57600, 9600 or 115200)
*/
/**************************************************************************/
void Adafruit_Fingerprint::begin(uint32_t baudrate) {
  delay(1000); // one second delay to let the sensor 'boot up'

  if (hwSerial)
    hwSerial->begin(baudrate);
#if defined(__AVR__) || defined(ESP8266) || defined(FREEDOM_E300_HIFIVE1)
  if (swSerial)
    swSerial->begin(baudrate);
#endif
}

/**************************************************************************/
/*!
    @brief  Verifies the sensors' access password (default password is
   0x0000000). A good way to also check if the sensors is active and responding
    @returns True if password is correct
*/
/**************************************************************************/
boolean Adafruit_Fingerprint::verifyPassword(void) {
  return checkPassword() == FINGERPRINT_OK;
}

uint8_t Adafruit_Fingerprint::checkPassword(void) {
  GET_CMD_PACKET(FINGERPRINT_VERIFYPASSWORD, (uint8_t)(thePassword >> 24),
                 (uint8_t)(thePassword >> 16), (uint8_t)(thePassword >> 8),
                 (uint8_t)(thePassword & 0xFF));
  if (packet.data[0] == FINGERPRINT_OK)
    return FINGERPRINT_OK;
  else
    return FINGERPRINT_PACKETRECIEVEERR;
}

/**************************************************************************/
/*!
    @brief   Ask the sensor to take an image of the finger pressed on surface
    @returns FINGERPRINT_OK on success
    @returns FINGERPRINT_NOFINGER if no finger detected
    @returns FINGERPRINT_PACKETRECIEVEERR on communication error
    @returns FINGERPRINT_IMAGEFAIL on imaging error
*/
/**************************************************************************/
uint8_t Adafruit_Fingerprint::getImage(void) {
  SEND_CMD_PACKET(FINGERPRINT_GETIMAGE);
}

/**************************************************************************/
/*!
    @brief   Ask the sensor to convert image to feature template
    @param slot Location to place feature template (put one in 1 and another in
   2 for verification to create model)
    @returns FINGERPRINT_OK on success
    @returns FINGERPRINT_IMAGEMESS if image is too messy
    @returns FINGERPRINT_PACKETRECIEVEERR on communication error
    @returns FINGERPRINT_FEATUREFAIL on failure to identify
   fingerprint features
    @returns FINGERPRINT_INVALIDIMAGE on failure to identify
   fingerprint features
*/
uint8_t Adafruit_Fingerprint::image2Tz(uint8_t slot) {
  SEND_CMD_PACKET(FINGERPRINT_IMAGE2TZ, slot);
}

/**************************************************************************/
/*!
    @brief   Ask the sensor to take two print feature template and create a
   model
    @returns FINGERPRINT_OK on success
    @returns FINGERPRINT_PACKETRECIEVEERR on communication error
    @returns FINGERPRINT_ENROLLMISMATCH on mismatch of fingerprints
*/
uint8_t Adafruit_Fingerprint::createModel(void) {
  SEND_CMD_PACKET(FINGERPRINT_REGMODEL);
}

/**************************************************************************/
/*!
    @brief   Ask the sensor to store the calculated model for later matching
    @param   location The model location #
    @returns FINGERPRINT_OK on success
    @returns FINGERPRINT_BADLOCATION if the location is invalid
    @returns FINGERPRINT_FLASHERR if the model couldn't be written
   to flash memory
    @returns FINGERPRINT_PACKETRECIEVEERR on communication error
*/
uint8_t Adafruit_Fingerprint::storeModel(uint16_t location) {
  SEND_CMD_PACKET(FINGERPRINT_STORE, 0x01, (uint8_t)(location >> 8),
                  (uint8_t)(location & 0xFF));
}

/**************************************************************************/
/*!
    @brief   Ask the sensor to load a fingerprint model from flash into buffer 1
    @param   location The model location #
    @returns FINGERPRINT_OK on success
    @returns FINGERPRINT_BADLOCATION if the location is invalid
    @returns FINGERPRINT_PACKETRECIEVEERR on communication error
*/
uint8_t Adafruit_Fingerprint::loadModel(uint16_t location) {
  SEND_CMD_PACKET(FINGERPRINT_LOAD, 0x01, (uint8_t)(location >> 8),
                  (uint8_t)(location & 0xFF));
}

/**************************************************************************/
/*!
    @brief   Ask the sensor to transfer 256-byte fingerprint template from the
   buffer to the UART
    @returns FINGERPRINT_OK on success
    @returns FINGERPRINT_PACKETRECIEVEERR on communication error
*/
uint8_t Adafruit_Fingerprint::getModel(void) {
  SEND_CMD_PACKET(FINGERPRINT_UPLOAD, 0x01);
}

/**************************************************************************/
/*!
    @brief   Ask the sensor to delete a model in memory
    @param   location The model location #
    @returns FINGERPRINT_OK on success
    @returns FINGERPRINT_BADLOCATION if the location is invalid
    @returns FINGERPRINT_FLASHERR if the model couldn't be written
   to flash memory
    @returns FINGERPRINT_PACKETRECIEVEERR on communication error
*/
uint8_t Adafruit_Fingerprint::deleteModel(uint16_t location) {
  SEND_CMD_PACKET(FINGERPRINT_DELETE, (uint8_t)(location >> 8),
                  (uint8_t)(location & 0xFF), 0x00, 0x01);
}

/**************************************************************************/
/*!
    @brief   Ask the sensor to delete ALL models in memory
    @returns FINGERPRINT_OK on success
    @returns FINGERPRINT_BADLOCATION if the location is invalid
    @returns FINGERPRINT_FLASHERR if the model couldn't be written
   to flash memory
    @returns FINGERPRINT_PACKETRECIEVEERR on communication error
*/
uint8_t Adafruit_Fingerprint::emptyDatabase(void) {
  SEND_CMD_PACKET(FINGERPRINT_EMPTY);
}

/**************************************************************************/
/*!
    @brief   Ask the sensor to search the current slot 1 fingerprint features to
   match saved templates. The matching location is stored in fingerID and
   the matching confidence in confidence
    @returns FINGERPRINT_OK on fingerprint match success
    @returns FINGERPRINT_NOTFOUND no match made
    @returns FINGERPRINT_PACKETRECIEVEERR on communication error
*/
/**************************************************************************/
uint8_t Adafruit_Fingerprint::fingerFastSearch(void) {
  // high speed search of slot #1 starting at page 0x0000 and page #0x00A3
  GET_CMD_PACKET(FINGERPRINT_HISPEEDSEARCH, 0x01, 0x00, 0x00, 0x00, 0xA3);
  fingerID = 0xFFFF;
  confidence = 0xFFFF;

  fingerID = packet.data[1];
  fingerID <<= 8;
  fingerID |= packet.data[2];

  confidence = packet.data[3];
  confidence <<= 8;
  confidence |= packet.data[4];

  return packet.data[0];
}

/**************************************************************************/
/*!
    @brief   Ask the sensor for the number of templates stored in memory. The
   number is stored in templateCount on success.
    @returns FINGERPRINT_OK on success
    @returns FINGERPRINT_PACKETRECIEVEERR on communication error
*/
/**************************************************************************/
uint8_t Adafruit_Fingerprint::getTemplateCount(void) {
  GET_CMD_PACKET(FINGERPRINT_TEMPLATECOUNT);

  templateCount = packet.data[1];
  templateCount <<= 8;
  templateCount |= packet.data[2];

  return packet.data[0];
}

/**************************************************************************/
/*!
    @brief   Set the password on the sensor (future communication will require
   password verification so don't forget it!!!)
    @param   password 32-bit password code
    @returns FINGERPRINT_OK on success
    @returns FINGERPRINT_PACKETRECIEVEERR on communication error
*/
/**************************************************************************/
uint8_t Adafruit_Fingerprint::setPassword(uint32_t password) {
  SEND_CMD_PACKET(FINGERPRINT_SETPASSWORD, (password >> 24), (password >> 16),
                  (password >> 8), password);
}

/**************************************************************************/
/*!
    @brief   Helper function to process a packet and send it over UART to the
   sensor
    @param   packet A structure containing the bytes to transmit
*/
/**************************************************************************/

void Adafruit_Fingerprint::writeStructuredPacket(
    const Adafruit_Fingerprint_Packet &packet) {
  SERIAL_WRITE_U16(packet.start_code);
  SERIAL_WRITE(packet.address[0]);
  SERIAL_WRITE(packet.address[1]);
  SERIAL_WRITE(packet.address[2]);
  SERIAL_WRITE(packet.address[3]);
  SERIAL_WRITE(packet.type);

  uint16_t wire_length = packet.length + 2;
  SERIAL_WRITE_U16(wire_length);

  uint16_t sum = ((wire_length) >> 8) + ((wire_length)&0xFF) + packet.type;
  for (uint8_t i = 0; i < packet.length; i++) {
    SERIAL_WRITE(packet.data[i]);
    sum += packet.data[i];
  }

  SERIAL_WRITE_U16(sum);
  return;
}

/**************************************************************************/
/*!
    @brief   Helper function to receive data over UART from the sensor and
   process it into a packet
    @param   packet A structure containing the bytes received
    @param   timeout how many milliseconds we're willing to wait
    @returns FINGERPRINT_OK on success
    @returns FINGERPRINT_TIMEOUT or
   FINGERPRINT_BADPACKET on failure
*/
/**************************************************************************/
uint8_t
Adafruit_Fingerprint::getStructuredPacket(Adafruit_Fingerprint_Packet *packet,
                                          uint16_t timeout) {
  uint8_t byte;
  uint16_t idx = 0, timer = 0;

  while (true) {
    while (!mySerial->available()) {
      delay(1);
      timer++;
      if (timer >= timeout) {
#ifdef FINGERPRINT_DEBUG
        Serial.println("Timed out");
#endif
        return FINGERPRINT_TIMEOUT;
      }
    }
    byte = mySerial->read();
#ifdef FINGERPRINT_DEBUG
    Serial.print("<- 0x");
    Serial.println(byte, HEX);
#endif
    switch (idx) {
    case 0:
      if (byte != (FINGERPRINT_STARTCODE >> 8))
        continue;
      packet->start_code = (uint16_t)byte << 8;
      break;
    case 1:
      packet->start_code |= byte;
      if (packet->start_code != FINGERPRINT_STARTCODE)
        return FINGERPRINT_BADPACKET;
      break;
    case 2:
    case 3:
    case 4:
    case 5:
      packet->address[idx - 2] = byte;
      break;
    case 6:
      packet->type = byte;
      break;
    case 7:
      packet->length = (uint16_t)byte << 8;
      break;
    case 8:
      packet->length |= byte;
      break;
    default:
      packet->data[idx - 9] = byte;
      if ((idx - 8) == packet->length)
        return FINGERPRINT_OK;
      break;
    }
    idx++;
  }
  // Shouldn't get here so...
  return FINGERPRINT_BADPACKET;
}

Is what I'm doing at all possible or am I just doing it wrongly?

I got it to work with NeoSWSerial and some help from AdaFruit. For those in the future:

Write the blank example sketch to the arduino
Go to device manager and switch the COM port that the arduino is connected to COM1 (Right click > Properties) - This applies even if you're using an FTDI breakout
Download and extract the SFG Demo Software
Click Open Device and select COM1
Change the baud rate (lower left corner) to 19200 - anything else seems unreliable (from my testing)
Replace all instances of SoftwareSerial to NeoSWSerial in the .cpp and .h files as well as your sketch. Change the finger.begin(57600) to finger.begin(19200) in the example sketches and that's it

If it doesn't work go back to device manager and change the baud rate on the COM port to 57600
Hope this helps someone!

Why don't they have that library take a Stream object so it doesn't matter what sort of serial you use?  Seems like this is an unnecessary dependency.