text:
Detecting the down time of a system by subtracting the time when the sytem gives ON signal and when it goes OFF
int pin_state = LOW;
struct Channel {
    byte pin;
    byte state;
    byte count;
    unsigned long fell, rose;  // times of fall and rise
};

const int CHANNEL_COUNT = 3;
Channel channels[CHANNEL_COUNT] = {
    { 2, LOW, 0, 0 },
    { 3, LOW, 0, 0 },
    //{ 4, LOW, 0, 0 },
    //{ 5, LOW, 0, 0 },
    //{ 6, LOW, 0, 0 }
};

void setup()
{
    for (int i = 2; i <= CHANNEL_COUNT; ++i) {
        pinMode(channels[i].pin, INPUT);
    }
    Serial.begin(9600);
    //Serial.println("pin,fell,rose,low time");
    Serial.println("Minutes, Seconds, Count");
}

void loop()
{
    for (int i = 0; i < CHANNEL_COUNT; ++i)
    {
        Channel &c = channels[i];
        byte new_state = digitalRead(c.pin);
        if (c.state == LOW && new_state == HIGH)   // input rose
        {
            c.rose = millis();
            c.count = c.count + 1;
        }
        else if (c.state == HIGH && new_state == LOW)  // input fell
        {
            c.fell = millis();
            display_channel(c);
        }
        c.state = new_state;
    }
}

void display_channel(const Channel &c)
{
  int minutes, seconds;
  unsigned long difference;
  difference = c.fell - c.rose;
  seconds = int(difference/1000);
  if (seconds >= 60)
  {
       minutes = seconds / 60;
       seconds = seconds % 60;
  }
    //Serial.print(difference/1000);
    //Serial.print(",");
    Serial.print(minutes);
    Serial.print(",");
    Serial.print(seconds/1000);
    Serial.print(",");
    Serial.println(c.count-1);
    //Serial.print(",");
  }

In this code, I tried to measure the time taken between the two events (when the ON signal comes and when the signal goes OFF) in two different channels simultaneously. But the code doesn't give any output and the serial monitor is empty except for the statement in the main function.
It would be useful if anyone could find where exact;y the problem is and a valid solution to it would be helpful.
edit : I made the following changes but still output is never displayed. Any error is still ON the program?

You have the same state being tested twice:
if (c.state == LOW && new_state == HIGH)   // input rose

and:
else if (c.state == LOW && new_state == HIGH)  // input fell

If "A", else if "A". It makes no sense. I think you wanted the second one to be the opposite:
else if (c.state == HIGH && new_state == LOW)  // input fell

Also, this calculation in display_channel doesn't work:
if (seconds >= 60)
{
  seconds = seconds % 60;
  minutes = minutes + 1;
}

For example, if seconds is 378, then seconds ends up as 18, and minutes as some undefined number plus 1.
That whole block should be replaced with:
minutes = seconds / 60;
seconds = seconds % 60;

In your code:

minutes starts off undefined
You add only 1 to minutes regardless of how many minutes have passed.

I have made the following changes as you suggested, but still, output doesnt gets displayed, Is there anything else left?


text:
Leonardo - always on power, status remains between computer reboots?
I'm looking for two answer here.

Is it possible to power a Leonardo to be always on, separate from the power from the USB host - I've tried with a full size Leonardo and a power adapter but for some reason the code didn't run when I did that. I've bought a battery shield too which will be arriving soon.
I want it be power-able via a switch with batteries so that I do a few things. For a start avoid it's boot up time and have it pressing a key as soon as the booted computer sees it (I'm running it as a keyboard/mouse via USB-HID) and also at one point I have the computer send serial data to have the Arduino run a different part of it's code...at this point the host computer reboots. Obviously that means the Arduino will see it's USB host disappear then come back online, will that automatically reset it and thus start it from the beginning again, or can I set it so that with always on power it will carry on doing what it is, irregardless of it's connecting to the host?

Do I need to change code, or libraries to achieve any of this?
With the theory intact answered, here is some of my actual code, i've stripped most of it out as it's just a bunch of keyboard presses
#include <Keyboard.h>
#include <Mouse.h>
char returnKey = KEY_RETURN;
char tabKey = KEY_TAB;
void setup() {
Keyboard.begin();
Mouse.begin();
// delay(60000); //Deploy Delay
delay(3000); //Testing Delay
// Keyboard commands
Keyboard.write(returnKey);
delay(14000);
// Welcome Screen
Mouse.click(MOUSE_LEFT);
delay(100);
}

void loop() {
}

Please show us the code and tell us which libraries you use and where they come from (only for libraries that are not standard included with arduino). Beside the arduino keyboard there are other ways to implement a usb keyboard: https://github.com/NicoHood/HID/wiki/Keyboard-API

Have added an example of my code

When do you expect those keyboard and mouse commands to execute?

@Majenko, at the moment 3 seconds after it's connected to the computer. Or instantly ideally. I plug the power barrel in and the ON and L leds light up - but nothing happens when I plug the USB in. I have to remove the power barrel and then it appears to reconnect to the USB and begin operating. It's as if the power barrel is stopping the USB port from doing anything on my device.

Well, they run 3 seconds after the board is powered up. Regardless of what the USB is doing. I am not aware of any way of saying "Run this once the USB is connected" in the current API.

@Majenko good point, I did consider this - however I also had a 60 second delay and plugged it in a few seconds after the power was fed to it and it didn't do anything. I also have another sketch where I trigger a sketch via a serial command in Terminal but when using the power barrel the Mac doesn't even see it until I remove the barrel. Maybe I have a faulty board that is disabling USB when powered from the barrel? (I'm quite happy for it to run code as soon as powered on, if I need a longer delay I could just trigger it with an external button)

put some code into loop()  ..... right now, you cannot tell if the sketch crashed or if it ran all way through

@jsotola but that's not really my problem at the minute. When I plug in with USB the sketch runs, as soon as I connect the barrel jack, it seems to disengage the USB connection. I'm using an official Arduino Leonardo too made in Italy, not a clone.

Is it possible to power a Leonardo to be always on, separate from the power from the USB host

Yes, that is what the barrel jack is for.

I've tried with a full size Leonardo and a power adapter but for some reason the code didn't run when I did that.

Then your code is wrong. Are you using while (!Serial); or something similar near the top of your code?

For a start avoid it's boot up time

The most certain way of doing that is to not use the bootloader. Instead program the board directly with a hardware programmer disabling (or erasing) the bootloader.

Obviously that means the Arduino will see it's USB host disappear then come back online, will that automatically reset it and thus start it from the beginning again, or can I set it so that with always on power it will carry on doing what it is, irregardless of it's connecting to the host?

The Leonardo only reboots if you open the serial port at 1200 baud, or toggle the RESET pin / button.

Do I need to change code, or libraries to achieve any of this?

It sounds like you may need to, yes - since it's not working at the moment when if the code were correct it should work.

IMPORTANT
Most computers will not recognize the Leonardo until the operating system is fully booted. This means you cannot use the Leonardo to interact with the BIOS or boot menu. The Leonardo does not implement the "Boot Protocol" keyboard which is required to interact with the BIOS or other pre-boot environment.

Thanks Majenko - it looks like I can do what I want in theory then. No "while (!serial)" at the top now, but as soon as I used the barrell connector on my full size Leonardo the code stopped running - it powered on and then it just seemed to ignore the USB connection.
Fortunately in my testing the macOS works with the default keyboard and with the BootKeyboard available in the HID-Project library, so I'm covered there too fortunately.

Have added an example of my code

It is possible to tell if the computer has opened or closed the serial port.
The serial port is located on the Arduino board.
By testing if(Serial) you can check if the serial port has been made active by the computer.
You could send keyboard and mouse events after it became active.
The fading in and out of the led at pin 13 is done by the bootloader. You could upload the sketch with a programmer to run without bootloader.
As far as I know, even without bootloader the serial port is still created.
The Teensy boards have a little more control over the USB interface.
To know what is going on and when a computer is connected, a mini linux computer is a lot easier. For example a Raspberry Pi.
The ATmega32u4 of the Arduino Leonardo has the possibilities and the information is available, but as far as I know, there are no libraries functions to use it.

source: Stack Exchange

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

sort: votes


text:
Sound localization using two mics, Arduino Uno on MATLAB
I have been trying to achieve this for a long time using the ITD method and have gone through various articles on the net.
I want to know if its possible to actually achieve sound localization using an Arduino Uno and two MEMS mics with a high gain (https://www.sparkfun.com/products/9868).
I have been trying this on MATLAB using the a=arduino() command and readVoltage command but the main issue I face is that for a particular sound (clapping for instance) the time difference between the two mics is not always the same which results in different direction predictions.
We managed to increase the low resolution of the Arduino by removing unnecessary operations. Now we are able to get an array of size 750 for 10 secs giving a resolution of 0.01 secs. I am not sure if that is enough.
I basically have 3 arrays, one storing the sampling times, and the other two storing the amplitudes of the two analog inputs at that particular time in the first array.
Now I look for a peak in one and then the corresponding near peak in the second one and then compute the time difference. After this I can compute the angle using the speed of sound and the distance between the mics.
Please let me know how I can make this work or where I am going wrong.

Calculate the minimum distance given your setup. What do you get? And what parameter determines this and the increment/resolution? Also check your memory requirements. Remember that Uno has a total of 2K SRAM (and that must hold stack, heap, global variables).

What do you mean by minimum distance? The resolution improves with less number of operations and no delay statements. I tried changing the baud rate but it did not make a difference.

How far does sound travel (at normal room temperature and air pressure) in 0.01 sec and/or the time to perform an analogRead()? Software Engineering is also about "doing the numbers".

@MikaelPatel Do you mean to say I should put the sound source at a distance of at least ~3.43 meters (or multiples of this) for there to be measurable time difference?

How about the distance between the microphones? It is the delta between the source and the microphones you want to measure to determine the angle?

Yes,I'm sorry I meant that. But isn't there a better way out around 4 meters is a lot of distance between two mics...maybe to increase the resolution somehow? is the resolution proportional to the clock speed of the micro controller @MikaelPatel ?

Let us continue this discussion in chat.

Here is some info that might help you with the engineering: https://ese.wustl.edu/ContentFiles/Research/UndergraduateResearch/CompletedProjects/WebPages/fl09/rms3/Introduction.htm Please remember that the Arduino has a max sample rate of approx. 9 K samples per second when collecting all samples on the Arduino before processing.

I'm voting to close this question as off-topic because the limitations of an Arduino mean that it is not a useful part of a practical solution to the problem.  Further, an MCU board is entirely unnecessary here; instead of using an Arduino, you should just route your two microphones to the PC's stereo microphone inputs, and surely Matlab has some capability or plugin that can capture audio from there.  If your PC doesn't have stereo mic inputs, get a suitable solution to that problem like a stereo USB audio ADC (beware the cheap ones are mono, and you can't use two for this).

@ChrisStratton I wanted to build something wearable for source localization. Also I don't think I can connect the MEMs mics to the laptop.

If you are building a wearable, you cannot usw matlab for processing. Iit doesn't work on an Arduino. or you will habe to use an embedded system (that might work). Doing the processing on the Arduino might be the bigger Problem, depending in the logic.

You can absolutely connect analog output MEMS microphones to a laptop with analog stereo in; for digital out ones you'd need a suitable USB interface chip.  A higher end ARM MCU might be able to do it, but not an ATmega-based Arduino.  Even if your goal is to make something wearable, you should gain experience with the algorithms on a PC first.   Then port the algorithm to a smartphone type SoC or possibly a high end bare-metal ARM part (or if it's your preference, maybe a dsPIC)

@ChrisStratton thanks for the advice. Could you guide me to a suitable and reasonable analog stereo input device/jack I can buy for two mems microphones(https://www.sparkfun.com/products/9868).

Selecting PC peripherals is not really on topic here.  Just be sure you get something that has actual stereo input; the cheap dongle ones are typically only mono input, either with the channels shorted together or only one connected (but will have "stereo" in the name as their output side is).  You might try audio-oriented forums for recommendations.

@ChrisStratton I have asked the question  in sound stackexchange- https://sound.stackexchange.com/questions/44280/connecting-two-mems-mics-to-laptop-for-sound-source-localization

Let's assume a microphone distance of 0.5m (which may be just small enough for you). Sound travels with about 300m/s in normal conditions. Let's also say, that you want at least a precision in the angle measurement of 15°.
As stated in the project Mikael linked, it is important that the distance to the sound source is big enough (so that the waves can be seen as planar). Then you have the following situation:

We are interested in the difference in distance, that the waves have to travel to the two microphones. It can be calculated by delta s = d * sin(alpha). With 15° we get delta s = 0.13m. The time difference is calculated by delta t = delta s/v, where v is the speed of sound. We get delta t = 0.43ms which equates to 2.32kHz sampling frequency. Since we use two microphones that must be sampled sequentially, the sampling frequency must be doubled. In the end we have a sampling frequency of 4.64kHz. So your sampling time of 0.01s wouldn't be enough for that.
The largest time difference in this setup (with the sound source in line with the microphones) would be 1.6ms, so your sampling time would be too big even for this.
Regarding the transmission with a baudrate of say 115200 baud this shouldn't be a problem.
But the actual speed of your setup highly depends on your code, which you haven't shown. Maybe this forum post can help you going further.

Yes, but using an Arduino to sample audio on behalf of a PC only introduces extra complexity while drastically reducing the quality and amount of information compared to the internal sound card.

@chrisl Thanks for the detailed well explained answer. I'll try the procedure in the link. Please tell me if using a better micro controller (like- the NRF52 series https://www.sparkfun.com/products/13990) help in getting a better resolution.

also is there a way to speeden up readVoltage on Matlab somehow to get this working maybe to a less precision of 30-90 degrees and d=1-1.5m.

I don't know anything about the matlab functions. But Chris is right, that it will be easier to achieve with a direct connection from microphone to PC.

You should use the Arduino interrupt function.
This will get it to 4 micros. You cannot use delay on Arduino counting in micros that is needed.
You can have ca 10 cm between mics doing as follows:
You may use accelerometer instead of mic.
Serial read, don't work, too slow. Use ISR..together with Arduino clock is 16 MHz.
Gives a error in +- 10 micros.
Given that it's possible to get the angle within 0.5 degrees if using Sine/Cosine. But, the trigg appear at different places on the waves sinus, giving you extra errors at low freq.
Don't give up.  This works:

Attach interrupt (ISR) on 2 pins. Make all variable used in ISR volatile.
Use internal clock with micros() to stop at interrupt, flag a variable true if rising/falling/change.
Use the time difference from trigs for calculations.
Calculations do in loop, not ISR calculate using radians.
Don't try to read or write anything while in ISR or before calculations, that mess up the clock!
Use 11500 baudrate.
If in loop or ISR = true then disable interrupt by state variable.

I fixed a bunch of things in this post.  Please fix more and avoid texting shorthand.

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


text:
Simulate 9-pin joystick output

I have built this little setup, which is supposed to record and replay input from a classic 9-pin Joystick. I connected the 9 pin connectors to the Arduino, read the input on the left side from the Joystick, and then passed it to the right side by setting the corresponding pins to HIGH.
It does work, and I can play games on the Commodore 64, however, I noticed that with this setup current is passed to the Commodore 64, which is very likely harming the machine a lot (I stopped immediately after noticing).
So my question is: how do I need to modify this setup so that no current is going from the Arduino to the Commodore 64 anymore?
Picture of the setup:

I would isolate the two devices using opto-isolators.

simulate this circuit – Schematic created using CircuitLab
Turning the output ON will illuminate the infra-red LED in the opto-isolator which turns on the photo-transistor connecting the input to GND. Both devices are then completely galvanically isolated (unless of course you take power from the C64 for the Arduino).
Another option, if you don't care about galvanic isolation, is to just use a simple transistor (small signal NPN or logic level N-channel MOSFET) to make an Open Drain output:

simulate this circuit
Again, set the output HIGH and the transistor will turn on connecting the C64 input to ground.

Thank you (again, I guess, as you pop up with solutions for every single question I ask ;) ) Majenko. I will look into both options, that was very helpful.

@Majenko can it be transistor 2N2222?

@MichałStępień Yes, that is an ideal and common transistor.

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


text:
Switch case (millis()) UPDATED
I want to create a sketch that counts the days from the moment the "project" start and send and osc message every two days (or more) for 3 weeks. So:

day zero : osc message -> 0
day two. : osc message -> 1
day four : osc message -> 2

etc.
I'm trying to create a state machine to send the messages when the millis reaches a certain time it should print message and so on for the other times.
I'm giving a small example:
I went with @jsotola's suggestion and tried out the BlinkWithoutDelay approach. It seemingly works because I get serial prints around the correct millis() they are printed in 4fold or 3fold the messages.
EDITED CODE:
int daytwo = 25920; // for testing purposes other numbers then the actual millis()
int dayfour = 44400;

void loop() {
  unsigned long currentMillis = millis();   // store current time

  if (currentMillis == daytwo) {
    Serial.println("daytwo");
  }

  if (currentMillis == dayfour) {
    Serial.println("dayfour");
  }
}

Serial output:

    11:04:39.889 -> daytwo
    11:04:39.889 -> daytwo
    11:04:39.889 -> daytwo
    11:04:39.889 -> daytwo
    11:04:39.889 -> daytwo
    11:04:39.889 -> daytwo
    11:04:39.889 -> daytwo
    11:04:39.889 -> daytwo
    11:04:39.926 -> daytwo
    11:04:58.366 -> dayfour
    11:04:58.366 -> dayfour
    11:04:58.366 -> dayfour
    11:04:58.366 -> dayfour

declare a variable to hold the osc message number .... increment it every 48 hours and transmit message ... refer to the blinkWithoutDelay example sketch for the method of repeating an action in a non-blocking way

And comparison is == not =. What is your question?

Also, do not compare time with equality, that will never work reliably. (What if the test is not executed at that precise moment?)

If it “seemingly works”, what exactly is your question? The way you now test for the appropriate time (with a comparison based on equality) is really unreliable. Why do you not use the same logic as the “blink without delay” sketch (i.e. use  “equal or greater than”) so you cannot accidentally skip an event?

@StarCat if I use == then I thought it would create a single message (I only need 1 message per 2 days as described in the goal of the project before the question on how to achieve this. (first I got the millis() example then the statemachine example and know I tried the blinkwithoutdelay way as the comments advised me to do.))
The >= comparator  gives me an overflow of Serial.print (or osc messages) in this case. Any suggestions?

You have to remember: a millisecond lasts for an entire millisecond. That's an eternity for an Arduino.

You can calculate the day using int day = millis() / 86400000UL. Then use that inside you switch-case statement.

@LazyFatTree no, you did not use the blinkWithoutDelay approach .... please examine the blinkWithoutDelay sketch closely, read and understand what the comments say ... one thing that you should understand is that the if statement is true only once every interval, not multiple times like your code ... just increment a counter inside the if block ... use the counter value to print day

The following code is not very "clean" but easy to understand. Use a variable to hold the day, you have already printed and check in which interval you are. If you change the 2 day interval print a message and set the actDay variable to the number of the day you have already printed; to avoid repprinting it again.
int daytwo = 25920;
int dayfour = 44400;

int actDay = -1;

void loop()
{
  unsigned long currentMillis = millis();
  if (currentMillis < daytwo)
  {
    if ( actDay != 0 )
    {
      actDay = 0;
      Serial.println("dayzero");
    }
  }
  else if (currentMillis < dayfour )
  {
    if ( actDay != 2 )
    {
      actDay = 2;
      Serial.println("daytwo");
    }
  }
  else
  {
    if ( actDay != 4 )
    {
      actDay = 4;
      Serial.println("dayfour");
    }
  }
}

Thanks your example was most comprehensible for so I'm going to vote this a solve. If others think the above answer is best please up vote that to then!  @Peter-Paul-Kiefer thanks again!

int day = 0;
unsigned long prevMillis = 0;
const unsigned long MILLIS_PER_DAY = 86400000UL;

void setup()
{
  prevMillis = millis();
}

void loop() {
  if( millis() - prevMillis > MILLIS_PER_DAY )
  {
    // one whole day has passed
    day++;
    prevMillis += MILLIS_PER_DAY;

    // do the things you want to do at the beginning of a new day
    if( day==2 ) {
      Serial.println("daytwo");
    }
    else if (day == 4) {
      Serial.println("dayfour");
    }
  }
}

This is a more generic version. It checks if 24*60*60*1000 milliseconds have past since the last time the day rolled over. When this occurs, it will increment the current day and update prevMillis to have the value of millis() when the day started.
This also has the advantage that is will only run your "daily code" once.
And will also run, when some other task takes a long time. I your old code, you might miss the exact moment millis() is the value you are looking for, if some other code takes more than 1 ms.

Myself, I would prefer a solution like your's. But, I thought, it would be better to explain the principple and still think the OP is smart enough to extend the example if only he/she have understood the basics. Again, your solution is the better one. Please let me point you to some issues': You used the undeclared variable dayfour instead of 4.

After about 50 days the millis() counter overflows and starts with 0. For about 50 days the if block will not be entered, Then after that period the prevMillis will overflow to a value ~25032704. If only "daytwo" and "dayfour" the is not an error (only if the day variable overflows ;-)). But if the OP tries to add more cases or eventual a more generic solution, this could be a problem.

In a comment above you mentioned a very good solution that would bring your already "good" answer to the next level. int day = millis() / 86400000UL. The use a switch statement. It also would be easy extendable. Only, it would make a changes like resetting the days to 0 or whatever a little bit complicate. I regrette not have given that solution. ;-)

@PeterPaulKiefer good catch. Changed dayfour to 4. Thanks.


text:
Arduino Array Scope with SPI
when I try the following code the SPI works correctly (see oscilloscope plot)
#include <SPI.h>

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

void loop() {
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
  byte a[] = {0xC,0xFF,0xFF,0xFF};
  SPI.transfer(a, 4);
  SPI.endTransaction();
  delay(10);
}

However when I move the array declaration to the a global it doesn't work any more. (see next oscilloscope plot) Why is this?
#include <SPI.h>

byte a[] = {0xC,0xFF,0xFF,0xFF};

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

void loop() {
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
  SPI.transfer(a, 4);
  SPI.endTransaction();
  delay(10);
}

it is not necessarily anything related to SPI ... use byte a[] = {'a', 'b', 'c', 'd'}; and do serial.write(a[0]) to print a value to serial monitor ... see if the result is the same

From the code you show I don't see any problem. It should work. Hm...

When you call SPI.transfer(a, 4);, any "received data" is stored in your byte array, a[]. The original data is overwritten.
If you print out the contents of the array before and after the function call to SPI.transfer(), you will see in the serial monitor what is happening to your array contents.
Here are 2 test sketches to illustrate the difference between the array with a global scope, VS the one with a static scope.
Global Scope
// Sketch uses 2344 bytes (7%) of program storage space.
// Global variables use 193 bytes (9%) of dynamic memory.
#include <SPI.h>

byte a[] = {0xC,0xFF,0xFF,0xFF};

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

void loop() {
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println();
  SPI.transfer(a, 4);
  SPI.endTransaction();
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println('\n');
  delay(1000);
}

Static Scope
// Sketch uses 2410 bytes (7%) of program storage space.
// Global variables use 193 bytes (9%) of dynamic memory.
#include <SPI.h>

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

void loop() {
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
  byte a[] = {0xC,0xFF,0xFF,0xFF};
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println();
  SPI.transfer(a, 4);
  SPI.endTransaction();
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println('\n');
  delay(1000);
}

The following sketch should solve the problem. Using the const keword before the declaration of the b[] array is optional.
// Sketch uses 2436 bytes (7%) of program storage space.
// Global variables use 197 bytes (9%) of dynamic memory.
#include <SPI.h>
const byte b[] = {0xC,0xFF,0xFF,0xFF};

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

void loop() {
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
  byte a[] = {0xC,0xFF,0xFF,0xFF};
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println();
  SPI.transfer(a, 4);
  SPI.endTransaction();
  memcpy(a, b, sizeof(b));
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println('\n');
  delay(1000);
}

One last edit. The compile size can be reduced by 66 bytes thanks to the static keyword.
// Sketch uses 2370 bytes (7%) of program storage space.
// Global variables use 197 bytes (9%) of dynamic memory.
#include <SPI.h>
const byte b[] = {0xC,0xFF,0xFF,0xFF};

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

void loop() {
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
  static byte a[] = {0xC,0xFF,0xFF,0xFF};
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println();
  SPI.transfer(a, 4);
  SPI.endTransaction();
  memcpy(a, b, sizeof(b));
  for(int i = 0; i < 4; i++){
    Serial.print(a[i]);
  }
  Serial.println('\n');
  delay(1000);
}

For more information, see: Arduino.cc


text:
SPI Clock Signal not stable
I am probing the SPI Clock pin 13 with my analog discovery 2. Nothing else is connected. The clock signal is there but it rises over time. (see picture) Here is my code:
#include <SPI.h>
void setup() {
  // put your setup code here, to run once:
  SPI.begin();
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE0));
  pinMode(8, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  digitalWrite(8,LOW);
  SPI.transfer(0xF7);
  SPI.transfer(0xFF);
  digitalWrite(8,HIGH);
  delay(500);

}

What do you think is causing this? Thanks

SPI Clock pin 13... of... an UNO?

Which Arduino board you are using?  BTW, not related to your issue but for the proper use of SPI bus, move your  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE0)); to the loop before the data transfer, and close your SPI transfer with SPI.endTransaction(). Also, SS pin by default is set to pin 10, and automatically set to OUTPUT when you call SPI.begin().

Looks like a hardware problem. I tried your code, and my scope shows a very steady square wave.


text:
1Hz & 32Hz from 32.768 kHz on ATmega328P at 8MHz & DS3231 32K
I have a 32.768 kHz signal at the ATmega328P input.
I need to get 2 signals from this signal: 1Hz and 32Hz.
How well will it work?
How to do this with a ATmega328P Timer/Counter?
What gain will the Timer/Counter give compared to my solution?
void setup() {
   pinMode(S32768Hz_PIN, INPUT_PULLUP); // 32.768 kHz signal
   attachInterrupt(digitalPinToInterrupt(S32768Hz_PIN), s32768Isr, FALLING); // Pin 3
}

volatile bool s32768IsrWasCalled = false;  // ISR flag 32768Hz
void s32768Isr() {
   s32768IsrWasCalled = true;
}
uint16_t s32Counter = 0;
uint16_t s1Counter = 0;

void loop() {
  if (s32768IsrWasCalled) {
      s32768IsrWasCalled = false;
      s32Counter++;
      if (s32Counter == 1024) {
        s32Counter = 0;
        // 32Hz
      }

      s1Counter++;
      if (s1Counter == 32768) {
        s1Counter = 0;
        // 1Hz
      }
  }
}

Update 24.10.2022
I wrote my first timer 1 setup code. Will this run 32 times per second, indefinitely?
// ATmega328P 3.3V 8MHz, Timer 1 & DS3231 32768 Hz
void setupTimer1() {
    // Disables all interrupts
    cli();
    // Reset bits
    TCCR1A = 0;
    TCCR1B = 0;
    // Enable Timer 1 overflow interrupt (TOIE1)
    TIMSK1 = (1 << TOIE1);
    // PWM mode. Mode #7 (fast PWM, top is fixed at 10 bits = 1024)
    TCCR1A |= _BV(WGM10) | _BV(WGM11);
    TCCR1B |= _BV(WGM12);
    // External clock on T1 pin, on falling edge (DS3231 32768Hz pin)
    TCCR1B |= (1 << CS11) | (1 << CS12);
    // Enables interrupts
    sei();
    // pinMode(T1_pin, INPUT_PULLUP); ?
}

void loop() {
    // So get 1 Hz from 32 Hz?
    // There will be no data races here?
    if((pulse_counter % 32) == 0) {
        callback1Hz();
    }

    if((pulse_counter % 2) == 0) {
        callback16Hz();
    }
}

volatile uint8_t pulse_counter;
// Timer 1 Overflow (32 Hz)
ISR(TIMER1_OVF_vect) {
    pulse_counter++;
}

Thank you!

How well will it work? ... shouldn't you be the one who determines that? ... use a hardware divider, there are ICs suitable for that

Why don't you just measure? Do you have a scope available?

Oh, and hint: Don't use a flag in the ISR, increment the counter there instead.

You can edit your question to include the details and clarifications people are asking you about in the comments.

WHat accuracy do you need for 1Hz and 32Hz?  just logic level?

I can't use an external hardware divider. I can divide 1 signal into 2 signals only on ATmega328P. I use DS3231 32K output with accuracy ±2ppm.

@EdgarBonet I wrote my first Timer 1 setup code. Update from 24.10.2022. Will this run 32 times per second, indefinitely?

Yes, this looks like it should work. Time to test it.

@EdgarBonet So get 1 Hz from 32 Hz? There will be no data races here? if((pulse_counter % 32) == 0) { } I've updated my example in the header.

No data race, as you are reading a single-byte variable. But you are not doing edge detection.

I did not test your program but, just by looking at it, I would expect
it to work... provided you do not add more code! Obviously you will need
to add more code in order to do something useful with those signals, and
then thinks might break.
The problem with this approach is that the interrupt rate is pretty
high: the program gets interrupted every 30.5 µs. You may miss an
interrupt if either:

it fires while there is already an interrupt (or other critical
section) being processed, and that interrupt (maybe combined with
some other pending interrupt) takes more than 30.5 µs to
complete

you add more code to loop() and that function ends up taking more
than 30.5 µs.

The first condition should be obvious, but I would assume the risk is
quite low, as only a very poorly written ISR would take that long to
complete. Beware however of library code, as that might bring surprises.
The second condition is a bigger risk, although maybe less obvious. The
problem is that this loop() assumes the code within
if (s32768IsrWasCalled) is going to be called exactly once per
interrupt. This may not be the case: if the program gets bigger, you may
miss interrupts, and get the frequencies wrong.
A simple way to avoid the issue number 2 is to count the pulses within
the ISR, as PMF suggests in a comment. I would use a single counter for
this, and make it unsigned in order to guarantee that it wraps around
reliably:
volatile uint16_t pulse_counter;
void s32768Isr() {
    pulse_counter++;
}

void loop() {
    int signal_32Hz = (pulse_counter >> 9) & 1;
    int signal_1Hz = (pulse_counter >> 14) & 1;
}

Note that this is one of the few cases when you can access the volatile
multi-byte variable without disabling interrupts: since you only ever
care about one bit, there is no data race.
A better option, though, would be to use a hardware timer for this job.
I would suggest using Timer 1 in “counter” mode (external clock
source on pin T1). Using mode 7 (fast PWM, 10-bit) you get the
32 Hz signal entirely generated by the hardware. And then you can
use the timer overflow interrupt to generate 1 Hz. The interrupt
rate is now 1024 times lower. I let you check the datasheet for the
details.

Brilliant answer, as usual :)

Thank you, nice code and option!

@EdgarBonet What condition would be true for signal_1Hz? It if (signal_32Hz == 1) doesn't work once per second.

@Andre: signal_1Hz is a 1 Hz signal, with 50% duty cycle: it is 0 for half a second, then 1 for half a second. If you want a condition that is true only once per second (as opposed to being true during a whole half second) you will have to do edge detection on that signal. Alternatively, do change detection on pulse_counter&(1U<<15).


text:
avrdude: ser_open(): can't open device "/dev/ttyACM0": Permission denied - can't get out of that
I have an Arduino Pro Micro ATmega32U4 and I'm facing this error message on uploading:
         Copyright (c) Brian Dean, http://www.bdmicro.com/
         Copyright (c) Joerg Wunsch

         System wide configuration file is "//etc/avrdude.conf"
         User configuration file is "/home/lucas/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

         Using Port                    : /dev/ttyACM0
         Using Programmer              : avr109
         Overriding Baud Rate          : 57600
avrdude: ser_open(): can't open device "/dev/ttyACM0": Permission denied
avrdude: opening programmer "avr109" on port "/dev/ttyACM0" failed

avrdude done.  Thank you.

Problem uploading to board.  See https://support.arduino.cc/hc/en-us/sections/360003198300 for suggestions.

I can upload code if I open Arduino IDE through terminal with sudo, but I don't know if there is any problem with this.
the stats for ttyACM0 shows up like this
~ >>> stat /dev/ttyACM0
    Arquivo: /dev/ttyACM0
    Tamanho: 0          Blocos: 0          bloco de E/S: 4096   arquivo especial de caractere
Dispositivo: 0,5        Inode: 1319        Ligações: 1     Tipo de dispositivo: 166,0
     Acesso: (0660/crw-rw----)  Uid: (    0/    root)   Gid: (  987/    uucp)
     Acesso: 2022-10-23 17:13:33.897457466 -0300
Modificação: 2022-10-23 17:13:33.897457466 -0300
  Alteração: 2022-10-23 17:13:33.897457466 -0300
    Criação: 2022-10-23 17:13:33.307457434 -0300

I've tried:
sudo chmod a+rw /dev/ttyACM0
sudo usermod -a -G uucp myUser
sudo udevadm trigger
And none of these worked, this error keeps showing when I use the IDE as my regular 'non root' user (Before someone ask, yes, I logged off and entered again, to make sure that the groups were updated).
So, is there any other step that I'm missing?

every time that I try to flash anything to it I get this message ... that is not true ... you said I can upload code opening Arduino IDE .... please edit your post to describe the problem exactly

It doesn't normally manifest in a permission error, but I might as well mention while you're at this to make sure you have ModemManager disabled. Otherwise it may not be as obvious when you've fixed your current problem if it's there creating a similar looking one.

Is this Linux?  Did you check the default permissions and ownership of the /dev/ttyACM0 device (when it is newly created / before you alter it)? How's about your self - did you check what groups your login belongs to? Ultimately you can edit the Linux UDEV rules, but that's a bit drastic and we should look for a simpler solution.

At the risk of annoying you, check id -Gn to be sure that effective group membership really has propagated. This something that hasn't been shown. sudo udevadm trigger isn't going to anything for you if you haven't been messing with udev rules. "Permission denied" the string version of EACCES coming from the open call in avrdude's ser_posix.c. If everything said is correct, the only other pain points are things like SELINUX, AppArmor, snap, or other security/sandbox/container/virtualization environment.

well I checked a few stuff, my user belongs to the same group (uucp) as the device file, I've searched a little bit more about udev rules and added the file /etc/udev/rules.d/50-embedded_devices.rules and the only line I've added is SUBSYSTEMS="usb", ATTRS{product}== "Arduino Micro", GROUP="users", MODE="0666" but nothing changed apparently


text:
Wemos: 16x2 display doesn't show anything
I connected a 16x2 LCD display to a Arduino Uno. Then I tested a "Hello, Word" code and it works perfect.
Now I want to do the same with a Wemos D1 Mini but it doesn't work.
Here the Wemos is not connected to USB:

This os the "Hello, World" code. I needed to change the name of the pins (maybe this is the problem):
#include <LiquidCrystal.h>

const int rs = 8, en = 7, d4 = D5, d5 = D4, d6 = D3, d7 = D2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void setup() {
  lcd.begin(16, 2);
  lcd.print("hello, world!");
}

void loop() {
  lcd.setCursor(0, 1);
  lcd.print(millis() / 1000);
}

This is the result (potentiometer works perfect):

A first step might be to clear out the code in loop() so that you can narrow down the issue. Just do the items in setup() so they happen only once. After you get text there, you can move on to more complex action. Of note, though, is that Wemos boards are 3.3V and LCDs are typically 5V. It doesn't look like you're level-shifting, though.

Although an old question, i just ran into the excat same issue.
The problem is that the pin numeration on the wemos D1 isn't the same as on the arduino.
I've followed the liquid crystal arduino tutorial but changed the numeration of the pins to
const int rs = 12, en = 13, d4 = 14, d5 = 4, d6 = 5, d7 = 16;

Now, at least for me, the display works as it should

thx, or can be defined like: const int rs = D6, en = D7, d4 = D5, d5 = D2, d6 = D1, d7 = D0;

You are doing it on wemos d1 mini isnt it ?
Then you dint include its header files,
Did you check the "LiquidCrystal.h" has definitions for wemos pinouts?
Your lcd is fine, n wemos too, its just your configuration is wrong.
Check those and update here.

Three possibilities (it's impossible to be more accurate from your description):

The display isn't wired to the pins you specified in your sketch
The display doesn't accept 3.3V signals when run from 5V
The display doesn't function when run from 3.3V

It's certainly not being initialized, which tells me that the instructions for setting it up aren't getting through, or aren't being executed when they do get through.
You can:

Use an oscilloscope or logic analyzer to confirm the right pins are in use,
Try powering the display from 3.3V if it's currently powered by 5V
Try powering the display from 5V if it's currently powered by 3.3V

If it's powered by 5V you may want to consider adding some logic level translation to boost the IO signals from the Wemos to 5V.

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


text:
nRF24L01 Problem
I'm trying to code a simple transmitter - Receiver program with nRF24L01
Very simple code. Compiles. But when I try to test it using serial monitor. But only the first character is printed on the screen just once.
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

#define CE_PIN 9
#define CSN_PIN 10

const uint64_t pipe = 0xE8E8F0F0E1LL;

RF24 radio(CE_PIN, CSN_PIN);

int smth[1];  // the transmitter data
int x=0;  // the copy of the receiver data
char rec[1]; //the receiver data

int ledPin = 3; // choose the pin for the LED
int inPin = 7;   // choose the input pin (for a pushbutton)
int val = 0;     // variable for reading the pin status

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);  // declare LED as output
  pinMode(inPin, INPUT);    // declare pushbutton as input

  radio.begin();
  radio.openWritingPipe(pipe);  //originally transmitter
}

void loop(){
  val = digitalRead(inPin);  // read input value
  if (val==HIGH) {         // check if the input is HIGH (button released)
    digitalWrite(ledPin, HIGH);  // turn LED OFF
    Serial.println('1');
    smth[0] = '1';
    radio.write(smth, sizeof(smth));
  } else {
    digitalWrite(ledPin, LOW);  // turn LED ON
    Serial.println('0');
    smth[0] = '0';
    radio.write(smth, sizeof(smth));
  }
}

Serial Monitor :
0

Instead of printing a zeros for infinite time till I change the mode of the switch, even though if I change the mode of the switch from low to high, nothing is printed on the screen.
I'm using Library for instance http://playground.arduino.cc/InterfacingWithHardware/Nrf24L01
Any help?

What library are you using?

Try changing int smth[1]; to byte smth[1];.

Solder capacitors to the power pins of the NRF24L01. 100uF would do.

I ran your code on my arduino pro mini / nRF24L01 with the "RF24 by TMRh20" library and got a continuous stream of zeros out on my monitor.

A quick look at the library header files shows you should call radio.stopListening() before calling radio.write() for the module to switch to transmit mode. This could be what is blocking the radio.write in the else block. I also recommend you try a byte array first, to get things working, just in case ints are the issue.

Completing TisteAndii reply I suggest to have a look at init. According to the RF24 classe list, it seems radio.begin(); and radio.openWritingPipe(pipe); are "void" function.
I personnaly use NRFLite from Dave Parson and his lib send a return value for his _radio.init function.
That's interesting because a lot of lib have a "send feature" which don't return until the receiver replied. So if you turn on your nRF and send data while the receiver is OFF, you're blocked. With a test at init, you can check that and loop until the receiver is available.
Note: I let my answer, but that's not the good one. As indicate in the coment, the init function dont tell if the receiver is avaible, but only if the nRF is connected (your nRF, so not the other one).

There's a bit of a point to not doing things blindly, yes.  But you have mis-stated it.  What Dave Parson's function returns has nothing to do with the status of the other end, rather it merely indicates success in communicating with the local chip by reading back the configuration - it does not indicate anything about the remote end being powered or not as you seem to believe.  With the normal RF24 you can easily read status to check wiring, also it does not block eternally but only for a given number of retires and only in the mode where it expects acknowledgement.

Agree! I suppose it depend on the LIB? In other cases, if you have a way to send and check the result, please tell as there is a lot of question about that and it seems the results are never as expected.


text:
LMT84 temperature sensor measurement error
I want to measure atmospheric temperature with an Arduino. The sensor I am using is an LMT84.
After uploading the following code to the Arduino board I am getting very high temperatures in the serial window.
I am unable to understand what the error in my code is. I've connected a 0.1 μF cap between Vcc and ground, and the data pin is connected to A1 on the Arduino.
Please check the following code:
const int sensor = A1; // assigning analog pin A1 to variable 'sensor'
float tempc;  // variable to store temperature in degree Celsius
float vout;   // temporary variable to hold sensor reading
float vout1;  // temporary variable to hold sensor reading

void setup()
{
  Serial.begin(9600);
  pinMode(sensor, INPUT); // configuring pin A1 as input
}

void loop()
{
  vout = analogRead(sensor);
  vout1 = (vout * 500) / 1023;
  tempc = vout1; // storing value in degrees Celsius
  Serial.print("LMT84 temp=");
  Serial.print(tempc);
  Serial.println();

  delay(1000);
}

The serial window shows these values:
LMT84 temp=168.13
LMT84 temp=168.13
LMT84 temp=168.64
LMT84 temp=168.89
LMT84 temp=168.13

The Arduino uses an analog voltage as reference. It is default set to the Vcc of the microcontroller, which is about 5 V for an Arduino Uno. The function analogReference can be used to set something else as reference.
When that reference is not precisely 5.0 V, it is impossible to measure a voltage in a accurate way. It is almost never precisely 5.0 V. When using the USB connector to power the Arduino board, it might be somewhere between 4.5 and 5.0 V.
The Arduino Uno has an internal voltage reference of 1.1 V. That is better than using the default 5 V. The actual voltage can be 1.0 to 1.2 V, you have to put the actual value in your sketch.
The LMT84 has an output of 1034 mV at 0°C and 476 mV at 100°C. That means your calculation is not correct. In the datasheet are two ways to calculate the temperature, an accurate formula and a simple calculation.
You can avoid all these problems with a temperature sensor that has a digital interface to the Arduino board. For example the DS18B20. That is a cheap and accurate temperature sensor.


text:
Attach the Arduino ISR function to the class member
I intended to use a timer interrupt for limited instances of a class in my ESP32 Arduino project. My first code conception was as follows:
portEXIT_CRITICAL_ISR(&lock0);
  }

hw_timer_t * timer[3] = NULL;

class myClass
{
private:
  irqCallback timmerCB;
  volatile uint8_t pri_var1, pri_var2;
  static uint8_t class_instance_number=0;
public:
  volatile uint8_t pub_var1, pub_var2;
  myClass(/* args */);
  ~myClass();
};

myClass::myClass(/* args */)
{
  timmerCB=timerCBArray[class_instance_number];
  timer[class_instance_number] = timerBegin(0, 80, true);
  timerAttachInterrupt(timer[class_instance_number], &timmerCB, true);
  class_instance_number++;
}

However, I have this problem: how can I change the variable inside the interrupt regarding to each class instance?

I know this is a late answer but I think it is possible to get past the problem with this if you use std::bind
Below is a full example but if that is too long to read,  here is a minimal example.
class ISRClass {
public:
  ISRClass(int pin) : pin_(pin) {}

  void setup() {
    attachInterrupt(digitalPinToInterrupt(pin_),
                    std::bind(&ISRClass::sensePinIsr, this), CHANGE);
  }

private:
  int pin_;
  ulong change_count_;

  void IRAM_ATTR sensePinIsr() {
    // do something fast and simple
    change_count_++;
  }
};

The function returned by std::bind takes no arguments, not even this.
Full example follows.
Here is an example.  This class uses interrupts to simply set the state of a member variable when the pin has changed state.  It then only reads the pin when needed.  You still have to query the member variable in the loop, but that is about 10x faster than reading the pin.
#include "FunctionalInterrupt.h"
#include <Arduino.h>
#include <functional>
#include <optional>
#include <map>

using CallBack = std::function<void(int)>;

class PinMonitor {
public:
  PinMonitor(int pin) : pin_(pin) {}
  void setup() {
    pin_state_ = digitalRead(pin_);
    attachInterrupt(digitalPinToInterrupt(pin_),
                    std::bind(&PinMonitor::sensePinIsr, this), CHANGE);
  }

  std::optional<int> CheckForNewPinState(int debounce) {
    if (!change_count_) {
      return std::nullopt;
    }
    if (!is_debouncing_) {
      is_debouncing_ = true;
      debouce_started_at_ = millis();
      return std::nullopt;
    }
    auto time = millis();
    if (time < debouce_started_at_) {
      debouce_started_at_ = time; // handle timer rollover
    }
    if (time < debouce_started_at_ + debounce) {
      return std::nullopt;
    }
    is_debouncing_ = false;
    change_count_ = 0;
    auto new_pin_state = digitalRead(pin_);
    if (new_pin_state != pin_state_) {
      pin_state_ = new_pin_state;
      for ( auto [_, callback] : callbacks_) {
        callback(pin_state_);
      }
      return pin_state_;
    }
    return std::nullopt;
  }

  int DoIfPinStateChanges(const CallBack callback) {
    next_callback_key++;
    callbacks_[next_callback_key] = callback;
    return next_callback_key;
  }

  void RemoveCallback(int key) {
    callbacks_.erase(key);
  }

private:
  int pin_;
  int pin_state_;
  ulong change_count_;
  CallBack callback_ = [](auto a) {};
  std::map<int, CallBack> callbacks_;
  bool is_debouncing_{};
  ulong debouce_started_at_{};
  int next_callback_key{};

  void IRAM_ATTR sensePinIsr() { change_count_++; }
};

Then in main you could use this like below.
NetworkConnection networkConnection;
OTAHandler otaHandler;
Logger &logger = Logger::getInstance();

PinMonitor pinMonitor1(16);
PinMonitor pinMonitor2(17);

int call_count{};
int removable_callback{};

void setup() {
  networkConnection.connect();
  logger.startWebSocket();
  otaHandler.setup();
  pinMode(16, INPUT_PULLDOWN);
  pinMode(17, INPUT_PULLDOWN);
  auto chip_id = ESP.getEfuseMac();

  pinMonitor1.setup();
  pinMonitor1.DoIfPinStateChanges([chip_id](auto a) {
    logger.infoln("chip %12llx, reports pin1 new state of %d detected", chip_id, a);
  });
  removable_callback = pinMonitor1.DoIfPinStateChanges([chip_id](auto a) {
    logger.infoln("second call back was called on pin1, new state of %d detected", a);
    call_count++;
  });
  pinMonitor2.setup();
  pinMonitor2.DoIfPinStateChanges([chip_id](auto a) {
    logger.infoln("chip %12llx, reports pin2 new state of %d detected", chip_id, a);
  });

}

void loop() {
  otaHandler.loop();
  logger.checkWebSocket();

  std::optional<int> new_pin_state1;
  std::optional<int> new_pin_state2;

  new_pin_state1 = pinMonitor1.CheckForNewPinState(100);
  if (new_pin_state1) {logger.infoln("new pin1 state is %d", *new_pin_state1);}

  new_pin_state2 = pinMonitor2.CheckForNewPinState(100);
  if (new_pin_state2) {logger.infoln("new pin2 state is %d", *new_pin_state2);}

  if (call_count > 5) {pinMonitor1.RemoveCallback(removable_callback);}

}

Interrupt Service Routine (ISR) outside a class
Let's consider a simple use of interrupts:
volatile bool switchChanged;

void switchPressed ()
  {
  switchChanged = true;
  }  // end of switchPressed

void setup ()
  {
  pinMode (2, INPUT_PULLUP);
  attachInterrupt (0, switchPressed, CHANGE);
  }  // end of setup

void loop ()
  {
  // whatever
  }  // end of loop

That compiles fine.

ISR inside a class as a class function (method)
Now let's imagine we want to put the interrupt handling into a class for our convenience.
class myClass
  {
  volatile bool switchChanged;

  public:

  void begin ()
    {
    pinMode (2, INPUT_PULLUP);
    attachInterrupt (0, switchPressed, CHANGE);   // <--- line 10
    }  // end of myClass::begin

  void switchPressed ()
    {
    switchChanged = true;
    }  // end of myClass::switchPressed

  };  // end of class myClass

myClass foo;  // make an instance of myClass

void setup ()
  {
  foo.begin ();
  }  // end of setup

void loop ()
  {
  // whatever
  }  // end of loop

That does not compile:
ISR_in_class_test.ino: In member function ‘void myClass::begin()’:
ISR_in_class_test:10: error: argument of type ‘void (myClass::)()’ does not match ‘void (*)()’

What is going on here?
ISRs have to be static functions, taking no arguments. However (non-static) class functions have an implied this-> pointer which points to the particular instance of the class.
For example, if we have two instances:
myClass foo;
myClass bar;

If we call foo.begin() then this-> points to "foo", and if we call bar.begin then this-> points to "bar".
However an ISR, when fired by the processor, cannot know whether this-> is "foo" or "bar" or something else. Thus the compiler cannot compile that line.

ISR inside a class as a static class function
We can try to work around this by making the class function static. Doing that means that the function is not tied to any particular instance, and thus the attachInterrupt line will compile.
class myClass
  {
  volatile bool switchChanged;   // <--- line 3

  public:

  void begin ()
    {
    pinMode (2, INPUT_PULLUP);
    attachInterrupt (0, switchPressed, CHANGE);
    }  // end of myClass::begin

  static void switchPressed ()
    {
    switchChanged = true;   // <--- line 15
    }  // end of myClass::switchPressed

  };  // end of class myClass

myClass foo;  // make an instance of myClass

void setup ()
  {
  foo.begin ();
  }  // end of setup

void loop ()
  {
  // whatever
  }  // end of loop

However now we have a different problem:
ISR_in_class_test.ino: In static member function ‘static void myClass::switchPressed()’:
ISR_in_class_test:3: error: invalid use of member ‘myClass::switchChanged’ in static member function
ISR_in_class_test:15: error: from this location

A non-static class variable cannot be called from a static class function. Why? Because the compiler doesn't know which variable you want. Is it foo.switchChanged or bar.switchChanged?

ISR inside a class as a static class function with static variables
To make the static function work, it can only access static variables. So we can make switchChanged static. Plus we need to define an instance of this static variable.
class myClass
  {
  static volatile bool switchChanged;  // declare

  public:

  void begin ()
    {
    pinMode (2, INPUT_PULLUP);
    attachInterrupt (0, switchPressed, CHANGE);
    }  // end of myClass::begin

  static void switchPressed ()
    {
    switchChanged = true;
    }  // end of myClass::switchPressed

  };  // end of class myClass

volatile bool myClass::switchChanged;  // define

myClass foo;  // make an instance of myClass

void setup ()
  {
  foo.begin ();
  }  // end of setup

void loop ()
  {
  // whatever
  }  // end of loop

Now the class compiles. However we have thrown away most of the advantages of having a class in the first place, as we are forced to use a static function, and that static function can only access static variables.

Glue routines
To work around this problem we can write short "glue" routines. These are functions that interface between an ISR and an instance of a class.
class myClass
  {
  volatile bool switchChanged;

  static myClass * instances [2];

  static void switchPressedExt0 ()
    {
    if (myClass::instances [0] != NULL)
      myClass::instances [0]->switchPressed ();
    }  // end of myClass::switchPressedExt0

  static void switchPressedExt1 ()
    {
    if (myClass::instances [1] != NULL)
      myClass::instances [1]->switchPressed ();
    }  // end of myClass::switchPressedExt1

  public:

  void begin (const byte whichPin)
    {
    pinMode (whichPin, INPUT_PULLUP);
    switch (whichPin)
      {
      case 2:
        attachInterrupt (0, switchPressedExt0, CHANGE);
        instances [0] = this;
        break;

      case 3:
        attachInterrupt (1, switchPressedExt1, CHANGE);
        instances [1] = this;
        break;

      } // end of switch
    }  // end of myClass::begin

  void switchPressed ()
    {
    switchChanged = true;
    }

  };  // end of class myClass

myClass * myClass::instances [2] = { NULL, NULL };

// instances of our class
myClass foo;
myClass bar;

void setup ()
  {
  foo.begin (2);   // pin D2
  bar.begin (3);   // pin D3
  }  // end of setup

void loop ()
  {
  // whatever
  }  // end of loop

This is a bit fiddly, however what it is doing is remembering in an array which instance of the class is associated with which interrupt. The "glue" routines switchPressedExt0 and switchPressedExt1 call the appropriate instance of the switchPressed function by using the remembered class pointer.
Now the non-static function switchPressed can access non-static class variables.

This answer was reproduced from my forum, but I can't post link-only answers here.

The Glue routines make myclass only work for specific scenarios. Can you use myclass as a base class and then use inheritance to create new class definitions for each scenario?

I tried it and realized inheritance does not work since we inherit the static variable. Creating two classes with identical code and different names works...but that's duplicated code which is also not a clean solution.

@PhilippWerminghausen You only have a fixed amount of hardware. It is hard to make a general class (which you might instantiate hundreds of times) but which have to share a single timer or interrupt. Compromises have to be made.


text:
Arduino potentiometer (external power) with amplifier
i am trying to make some kind of an amplifier. I got an amp board but want to read out the value from the potentiometer. The problem is that this pot is connected to the amp and has to be connected to the amps power Is there any way i can still read data (with an arduino) so that i can have a volume percentage on a lcd? Or is this imposible?
Amp 24v Potentiometer = 6pin. B50k
also what zould happen if i connect a 10k resistor instead of a 50k ressistor (audio potentiometer) what would the effect be?

Would this work??
btw thanks for helping!
https://www.aliexpress.com/item/2PCS-Precision-097-9mm-potentiometer-switch-biaxial-triple-50K-double-100K-rotary-handle-length-17-5mm/32811342965.html?spm=2114.search0104.3.15.50705d774mtDlF&ws_ab_test=searchweb0_0,searchweb201602_5_10065_10068_10547_319_317_10548_10696_10084_453_454_10083_10618_10304_10307_10820_10821_538_537_10302_536_10059_10884_10887_100031_321_322_10103,searchweb201603_51,ppcSwitch_0&algo_expid=5693c9b0-3022-443b-8f65-c4ca408cc919-2&algo_pvid=5693c9b0-3022-443b-8f65-c4ca408cc919

and does it mater that the last one is 100k (i need (50k) can i use the 100k for the arduino?

or this???
https://www.aliexpress.com/item/2PCS-LOT-09-type-precision-potentiometer-triple-B10K-axis-15MM-power-amplifier-volume-potentiometer-line-three/32830930075.html?spm=2114.search0104.3.9.50705d774mtDlF&ws_ab_test=searchweb0_0,searchweb201602_5_10065_10068_10547_319_317_10548_10696_10084_453_454_10083_10618_10304_10307_10820_10821_538_537_10302_536_10059_10884_10887_100031_321_322_10103,searchweb201603_51,ppcSwitch_0&algo_expid=5693c9b0-3022-443b-8f65-c4ca408cc919-1&algo_pvid=5693c9b0-3022-443b-8f65-c4ca408cc919

can you clarify the meaning of "some kind of amplifier". Do you want a preamplifier (signal voltage amplification), or a power amplifier (high current)?

high current 24 50amps per channel

This little board.
and i just want to be able to read from the potentiometer.
i am guessing i will have to find a triple pot or a quad pot...
https://www.aliexpress.com/item/50Wx2-TPA3116D2-Dual-Channel-DC-4-5-27V-Digital-Power-Amplifier-Board-Two-Channel-Stereo-High/32847729011.html?spm=a2g0s.8937460.0.0.79452e0epIatdy

It's impossible. The pot is most probably acting as a passive variable attenuator. As such the top end will be the incoming audio signal, the lower end will be ground, and the wiper will be the attenuated incoming signal. There's not a lot you can do with that.
You would need to replace the pot with an equivalent triple pot (if such a thing exists) and have one third of it connected to the Arduino.  The pot you have at the moment is a dual pot, and a log taper at that.
Alternatively adding some kind of quadrature (motor) encoder to the shaft of the pot may be a possibility.

A few options come to my mind:

I see you're using a double potentiometer, if you're using only one of it's outputs to control, you can use the other output to measure it's setting. (Or indeed use a "triple potentiometer" or added encoder as Majenko suggested.)
Use the Arduino as an intermediate (have the potentiometer as an input on the Arduino and control the output accordingly on the output of the Arduino).
Measure the output of the potentiometer. I'm not quite sure but the resistance over the potentiometer shouldn't be anything different depending on what is connected as well. Though you could also measure the output voltage on the potentiometer and from there deduce what it's value is (which may be difficult if it's an audio signal on this point in your system).

thanks for the comment i am using a double pot to have stereo i will try to get a triple pot do you think this one will work? even with 100k on the last one the reading should be the same right?

https://www.aliexpress.com/item/2PCS-Precision-097-9mm-potentiometer-switch-biaxial-triple-50K-double-100K-rotary-handle-length-17-5mm/32811342965.html?spm=2114.search0104.3.15.50705d774mtDlF&ws_ab_test=searchweb0_0,searchweb201602_5_10065_10068_10547_319_317_10548_10696_10084_453_454_10083_10618_10304_10307_10820_10821_538_537_10302_536_10059_10884_10887_100031_321_322_10103,searchweb201603_51,ppcSwitch_0&algo_expid=5693c9b0-3022-443b-8f65-c4ca408cc919-2&algo_pvid=5693c9b0-3022-443b-8f65-c4ca408cc919

I don't see why not, and for the price it's worth a shot? Quite interesting part actually, what would've been the odds of finding this locally ;p Though note it may be difficult to find a pinout of this pot, which is worth a check before ordering.


text:
Ov7670 (without FIFO) captures the images twice at the same time
I recently started working on an security camera system, with an arduino uno and an OV7670 camera without FIFO memory, and an ESP-8266 to transfer the images to a webserver. Everything is working, except this:
The problem: My camera takes the images (QVGA resolution) twice every time, and collapse them into one image.
My images looks like this:

One (240*320) QVGA image is built by two (120*320) half image.
My camera takes the two images AFTER each other, not just duplicates the first part.
(After I got one line of the image ready I send it with SoftwareSerial to ESP8266, and that send it forward...)
I'm trying to changeing the scaling registers with different combinations, without success.
I followed this tutorial at the beginning, and modified its code.
https://hkalasua.wordpress.com/2017/09/11/ov7670-arduino-sd/
Arduino code:
#include <Wire.h>
#include <SoftwareSerial.h>

SoftwareSerial ESPserial(10, 11); // RX | TX

void Init_YUV422(){
  WriteOV7670(0x12, 0x00);//COM7
  WriteOV7670(0x8C, 0x00);//RGB444
  WriteOV7670(0x04, 0x00);//COM1
  WriteOV7670(0x40, 0xC0);//COM15
  WriteOV7670(0x14, 0x6A);//COM9
  WriteOV7670(0x3D, 0x40);//COM13
  }

void Init_QVGA(){
  WriteOV7670(0x0C, 0x04);//COM3 - Enable Scaling
  WriteOV7670(0x3E, 0x19);//COM14
  WriteOV7670(0x72, 0x11);//
  WriteOV7670(0x73, 0xF1);//
  WriteOV7670(0x17, 0x16);//HSTART
  WriteOV7670(0x18, 0x04);//HSTOP
  WriteOV7670(0x32, 0xA4);//HREF
  WriteOV7670(0x19, 0x02);//VSTART
  WriteOV7670(0x1A, 0x7A);//VSTOP
  WriteOV7670(0x03, 0x0A);//VREF
  WriteOV7670(0x70, 0x00);//SCALING_YSC

  }

void Init_OV7670() {
  //Reset All Register Values
  WriteOV7670(0x12, 0x80);
  delay(100);

  WriteOV7670(0x3A, 0x04); //TSLB

  WriteOV7670(0x13, 0xC0); //COM8
  WriteOV7670(0x00, 0x00); //GAIN
  WriteOV7670(0x10, 0x00); //AECH
  WriteOV7670(0x0D, 0x40); //COM4
  WriteOV7670(0x14, 0x18); //COM9
  WriteOV7670(0x24, 0x95); //AEW
  WriteOV7670(0x25, 0x33); //AEB
  WriteOV7670(0x13, 0xC5); //COM8
  WriteOV7670(0x6A, 0x40); //GGAIN
  WriteOV7670(0x01, 0x40); //BLUE
  WriteOV7670(0x02, 0x60); //RED
  WriteOV7670(0x13, 0xC7); //COM8
  WriteOV7670(0x41, 0x08); //COM16
  WriteOV7670(0x15, 0x20); //COM10 - PCLK does not toggle on HBLANK
}

void WriteOV7670(byte regID, byte regVal) {
  // Slave 7-bit address is 0x21.
  // R/W bit set automatically by Wire functions
  // dont write 0x42 or 0x43 for slave address
  Wire.beginTransmission(0x21);
  // Reset all register values
  Wire.write(regID);
  Wire.write(regVal);
  Wire.endTransmission();
  delay(1);

}

void ReadOV7670(byte regID) {
  // Reading from a register is done in two steps
  // Step 1: Write register address to the slave
  // from which data is to be read.
  Wire.beginTransmission(0x21); // 7-bit Slave address
  Wire.write(regID);  // reading from register 0x11
  Wire.endTransmission();

  // Step 2: Read 1 byte from Slave
  Wire.requestFrom(0x21, 1);
  Serial.print("Read request Status:");
  Serial.println(Wire.available());
  Serial.print(regID, HEX);
  Serial.print(":");
  Serial.println(Wire.read(), HEX);
}

void XCLK_SETUP(void) {
  pinMode(9, OUTPUT); //Set pin 9 to output

  //Initialize timer 1

  //WGM13, WGM12, WGM11 & WGM10 bits SET- Fast PWM mode
  //COM1A0 SET- Toggle OC1A on compare match
  TCCR1A = (1 << COM1A0) | (1 << WGM11) | (1 << WGM10);
  //SET CS10 bit for clock select with no prescaling
  TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS10);
  //Output Compare Register 1A(OCR1A) = 0
  //This will lead to a match on every clock cycle
  //Toggle OC1A output pin on every match instance
  //Therefore, the generated waveform will have half
  //the frequency of the driving clock i.e. 8Mhz
  //OC1A pin- PB1 (alternate functn) pin i.e. Arduino pin 9
  OCR1A = 0;

}

// Two Wire Interface Setup
// Sets the frequency of the SCL line
// Default is 100KHz so we won't use this function
void TWI_SETUP(void) {
  //Set prescaler bits in TWI Status Register (TWSR) to 0
  TWSR &= ~3;
  //Set SCL frequency to 100KHz
  //SCLfreq = CPUfreq/(16 + 2(TWBR) - 4^(TWPS))
  //TWBR = 72, TWPS(prescaler) = 0
  TWBR = 72;

}

void OV7670_PINS(void) {
  //Setup Data input pins and Interrupt pins
  //DDRC bits 3:0 = 0 =>  bits configured as Data Inputs
  //DDRC 3:0 - A3,A2,A1,A0
  DDRC &= ~15;//low d0-d3 camera

  //~(0b11111100) = 0b00000011
  //make DDRD 7:2 = 0 => Inputs
  //d7-d4 as data inputs, d3-INT1 is VSYNC and d2-INT0 is PCLK
  DDRD &= ~252;
}

void QVGA_Image() {
  int h, w;

  while (!(PIND & 8));//wait for high
  while ((PIND & 8));//wait for low

  byte dataBuffer[320];

  h = 240;
  while (h--) {
    w = 320 ;

    while (w--) {
      while ((PIND & 4));   //wait for low
      dataBuffer[319 - w] = (PINC & 15) | (PIND & 240);
      while (!(PIND & 4));  //wait for high
      while ((PIND & 4));   //wait for low
      while (!(PIND & 4));  //wait for high
    }

    //sendig the line to ESP
    ESPserial.write(dataBuffer, 320);
  }

  delay(100);
}

void setup() {
  Serial.begin(115200);
  ESPserial.begin(115200);
   noInterrupts(); //Disable all interrupts
  XCLK_SETUP();   //Setup 8MHz clock at pin 11
  OV7670_PINS();  // Setup Data-in and interrupt pins from camera
  delay(1000);
  TWI_SETUP();    // Setup SCL for 100KHz
  interrupts();
  Wire.begin();

  Init_OV7670();
  Init_QVGA();
  Init_YUV422();
  WriteOV7670(0x11, 0x1F); //Range 00-1F
  // noInterrupts();

 QVGA_Image();

}

void loop() {
 /* ..Not relevant for this problem.. */
}

I'd be very greatful, if you can help!..
...this is a really annoying problem..

and modified its code - what did you change? - besides adding WriteOV7670(0x70, 0x00);

nothing special, I just removed the SD card parts, and inserted the serial commmunication with the  ESP. I didn't change the register values except that.

and what does that register do?


text:
avrdude: stk500_recv(): programmer is not responding: lilypad arduino
i realise this is probably the most common error that is asked about on this forum, but it is a major issue for me. i have an arduino lilypad main board (with the ATMega328P, boot loader already burned), and a generic FTDI serial to usb adapter plugged into my windows 10 laptop. When i try to upload the Blink program from the Arduino IDE, it fails with the error:
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0xfe
i am using a windows 10 laptop, the Arduino IDE from the windows store. this is a new lilypad, and i have never been able to upload to it. take note that when i reset the board, the pin13 light does flash (but  not the way the Blink program specifies, obviously.
i have already tried:

Rebooting my computer
Restarting the IDE
Turning the COM port on and off
Taking out the RX/TX wires from the FTDI converter
Pressing the reset button right before uploading (or during uploading)
Changing which board it is set as in the IDE
Unplugging and re-plugging the USB-Serial converter

if you have any other possible solutions they would be appreciated, thanks

does the board have a bootloader? 2)the programmer setting is ignored if you use serial upload 3) add a photo of the wiring

it does have the boot loader already, I will add a photo of the wiring tomorrow (GMT+10)

Sorry, probably irrelevant in this case, but AVRISP MKII is the enabled option in the IDE programmers section

what is "Taking out the RX/TX wires from the Lilypad"

Last time I bought one of the Lilypads, it did not have a bootloader. I had to buy a SMD programmer adapter that presses down over the 328P chip to bootload it as the board did not break out the ICSP pins to any pads.
I think I got mine here https://hobbyking.com/en_us/atmel-atmega-socket-firmware-flashing-tool.html but I haven't seen them in stock for a while.  Very handy tool tho. Another option is to tack wires to the appropriate uC pins and, connected to a 2x3 header that your Programmer can connect to. Remove the wires when done.

Thanks, how can I confirm if my Lilypad has a bootloader?

In the IDE, in File:Preferences, turn on Verbose outputs.  Press and hold reset, then start a download. When you see "Compiled xxx of 32,xxx bytes", release reset. You will see the down load attempted three times. It may take a few tries to get the timing right. If you can't ever get it working, then you probably don't have a bootloader.

the 2x3 points are for the ICSP header

Yes, I see the picture now. Add 2x3 male pins, and plug on a Programmer and put a Bootloader on the '328P.


text:
Digispark Attiny85 ultrasonic sensor input problem
I was trying to use ultrasonic with digispark Attiny85 board and used separate pins for trigger and echo, and used MM5451 led controller as a display, I uploaded the code successfully the problem is if the echo pin is connected to it at startup board stops/freezes I don't know but code doesn't work, and if I connect the echo pin few seconds after the board starts everything works fine.
Below is the code I wrote
#define clock 0
#define data 1
#define trig 2
#define echo 3
byte c[5]={10,11,11,0,12};
long dist=0;
const uint8_t digits[15]={
    B1110111,
    B1000100,
    B1101011,
    B1101110,
    B1011100,
    B0111110,
    B0111111,
    B1100100,
    B1111111,
    B1111110,
    B0111011,
    B0010011,
    B1011101,
    B0111001,
    B0000000
};
void setup()
{
    pinMode(clock,OUTPUT);
    pinMode(data,OUTPUT);
    pinMode(trig,OUTPUT);
    pinMode(echo,INPUT);
    digitalWrite(clock,LOW);
    digitalWrite(data,LOW);
    digitalWrite(trig,LOW);
}
void pulse()
{
    delayMicroseconds(5);
    digitalWrite(clock,HIGH);
    delayMicroseconds(10);
    digitalWrite(clock,LOW);
    delayMicroseconds(5);
}
long ultrasonic(boolean ci)
{
    long distance;
    unsigned long pulsetime;
    digitalWrite(trig,LOW);
    delayMicroseconds(5);
    digitalWrite(trig,HIGH);
    delayMicroseconds(10);
    digitalWrite(trig,LOW);
    pulsetime=pulseIn(echo,HIGH);
    if(ci)
    {
        distance=pulsetime/58;
    }
    else
    {
        distance=pulsetime/148;
    }
    delay(50);
    if((distance<450)&&ci)
    {
        return distance;
    }
    else if((distance<180)&&(!ci))
    {
        return distance;
    }
    else
    {
        return 0;
    }
}
void show(byte a[5])
{
    delayMicroseconds(5);
    digitalWrite(data,HIGH);
    pulse();
    for(byte x=0;x<5;++x)
    {
        byte data1=digits[a[x]];
        for(byte y=0;y<7;++y)
        {
            if(data1&(1<<y))
            {
              digitalWrite(data,HIGH);
                pulse();
            }
            else
            {
                digitalWrite(data,LOW);
                pulse();
            }
        }
    }
    digitalWrite(data,LOW);
    pulse();
}
void loop()
{
    show(c);
    delay(2000);
    while(1)
    {
        dist=ultrasonic(true);
        if(dist>0)
        {
            byte i=3;
            c[4]=14;
            c[0]=14;
            c[1]=14;
            c[2]=14;
            c[3]=14;
            while(dist>0)
            {
                c[i]=(dist%10);
                if(i==0)
                {
                    i=4;
                }
                dist/=10;
                --i;
            }
            show(c);
        }
        delay(200);
    }
}

Pins 3 and 4 are used for USB (during programming). Try using pin 5 instead.
Or swap it with one of the clock, data, or trig outputs (i.e. 0,1,2)

Gerben thanks for your replay, one thing I want to mention is I used same code and powered digispark with my phone otg and it's working and it doesn't work when I connect it to phone charger's USB output, weird right.

That  is weird indeed. Did my suggestion of swapping/changing pin(s) help?

That echo pin was sending pulse at startup without trigger. and it was messing with USB signals of bootloader at startup which making bootloader to stuck. I did what you said, swapped pin and it's working. But one problem is that USB singals on startup messing with my display by sending invalid data, I have to use pin 3,4 because 5th pin doesn't work  it is set as reset pin my board is digispark clone

Try some other combinations. Like for example using pins 3 and 4 for trig and data. Having the bootloader pulsing those won't have many side effects, as far as I can tell.


text:
Cannot get pins on esp 8266 adafruit wifi module to read HIGH on pin 15
I have an esp8266 and I cannot get the value to read HIGH when 3.3v is applied to directly to pin by hand. I have an Arduino Uno powering the esp8266. It connects to the WiFi like it should, and now all I want is to manually see that when I apply 3v that the state will change from 0 to 1. Does anyone know how I can do this.
When I apply 3 volts directly to pin 15 it outputs 0. Even if I try digitalWrite on the pin and set it to HIGH it still says 0 and i serialPrint. My end goal if to use the arduino uno to fire and ouput on pin 8. On the arduino UNO side I am using a super sonic sensor. When the sensor is triggered I want to turn pin 8 on. From there I want to take pin 8 to feed pin 15 on the 8266 as an input. Before I did that I just wanted to see that when you manually apply 3v that the pin would read 1 or HIGH but no matter I do it wont change value. Once I get that value as HIGH I can send  a second request to the server like im already but now I want to say  that there was an intruder. Im not sure why the value wont change but being a beginner with arduino Im trying to keep it simple and ideally would like to wire it in this manner.
#include <SoftwareSerial.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266WiFi.h>

const char* ssid = "********";
const char* password = "********";

HTTPClient http;

static const uint8_t D8 = 15;
int featherPin = D8;

//int trigPin = 13;
//int echoPin = 12;
//int ledPin = 10;
//int hornPin = 11;
//
//int spaceIntruded;
//
//long duration, cm, inches;

void setup() {
  Serial.begin(115200);
  pinMode(featherPin,INPUT);

  WiFi.begin(ssid, password);

  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("Waiting for connection");
 }

//  Serial.begin (9600);
//  pinMode(trigPin, OUTPUT);
//  pinMode(echoPin, INPUT);
//  pinMode(ledPin, OUTPUT);
//  pinMode(hornPin, OUTPUT);
//  delay(5000);
//  Serial.println("Armed...");

}

void loop() {

  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("yay connect");

    http.begin("http://10.150.40.121:3000/");
    http.addHeader("Content-Type", "text/plain");

    int httpCode = http.POST("Message from ESP8266");
    String payload = http.getString();
    Serial.println(payload);
    http.end();

    } else {
      Serial.println("Error in Wifi connection");
    }
//    digitalWrite(featherPin, HIGH);
    int sensorValue = digitalRead(featherPin);
    Serial.print(sensorValue);

//    if (digitalRead(featherPin) == HIGH) {
//      http.begin("http://10.150.40.121:3000/home");
//      http.addHeader("Content-Type", "text/plain");
//
//      int httpCode = http.POST("Message from ESP8266");
//      String payload = http.getString();
//      Serial.println(payload);
//      Serial.print("hi");
//      http.end();
//      } else {
//        Serial.print(featherPin);
//        Serial.println("I am not hot");
//      }

//  digitalWrite(trigPin, LOW);
//  delayMicroseconds(1);
//  digitalWrite(trigPin, HIGH);
//  delayMicroseconds(2);
//  digitalWrite(trigPin, LOW);
//
//  pinMode(echoPin, INPUT);
//  duration = pulseIn(echoPin, HIGH);
//
//  inches = (duration / 2) / 74;
//  Serial.println(inches);
//
//  spaceIntruded = inches;
//
//  if (spaceIntruded <= 50 || spaceIntruded >= 900){
//      digitalWrite(ledPin, HIGH);
//      digitalWrite(hornPin, HIGH);
//      Serial.println("Intruder Detected!");
//      Serial.println("Sending text Notification...");
//      delay(500);
//      Serial.println("Armed...");
//  }
//
//  else{
//    digitalWrite(hornPin, LOW);
//    digitalWrite(ledPin, LOW);
//  }
    delay(30000);

}

do you see how part of your code is properly formatted on gray background? .... that is because the text is indented by at least 4 spaces ....... please format the rest of the code ..... select all the code and click the {} icon

when I apply 3v that the state will change from 0 to 1 what are you applying 3v to? which pin? for how long? because you have a delay of 30 seconds in each loop - so you're only checking every 30 seconds

p.s. - I didn't think the esp8266 liked such long delays

also, what output are you currently getting with your code?

Right now when I apply 3 volts directly to pin 15 it outputs 0. Even if I try digitalWrite  on the pin and set it to HIGH it still says 0 and i serialPrint. My end goal if to use the arduino uno to fire and ouput on pin 8. On the arduino UNO side I am using a super sonic sensor. When the sensor is triggered I want to turn pin 8 on. From there I want to take pin 8 to feed pin 15 on the 8266 as an input. Before I did that I just wanted to see that when you manually apply 3v that the pin would read 1 or HIGH but no matter I do it wont change value. Once I get that value as HIGH I can send a...

a second request to the server like im already doing saying that there was an intruder. Im not sure why the value wont change but being a beginner with arduino Im trying to keep it simple and ideally would like to wire it in this manner.

Pin 15 is one of the boot configuration pins (0, 2, 15) and must be LOW at boot. To ensure it, dev boards with esp8266 have external pull-down on pin 15 (and pull-up on 0 and 2). To read the pin HIGH you must overcome the pull-down.
Adafruit Feather HUZZAH has 4.7kOhm resistor for the pull-down, so it is a 'strong' pull down. NodeMcu has 12kOhm resistor on io 15.
From schematics of Adafruit Feather HUZZAH

Note: setting pin as OUTPUT and HIGH doesn't make it read HIGH in code. Only INPUT pin state can be read with digitalRead (only on some MCUs digitalRead reads the same register set by digitalWrite).

This is unclear to me. What do you mean by overcome the pulldown? Could your break it down a little further or send me in a direction to find a resource that can clarify this. I having a hard time visualizing what you mean fully. Thanks again for taking the time to reply. I am also setting the input on line 36 as an input. I tried making forcing it HIGH to try a different idea but I know Im not fully versed with what I can and cannot do.

which esp 8266 adafruit wifi module you have exactly?

https://www.microcenter.com/product/460313/feather-huzzah-with-esp8266-wifi
Also it doesnt have to be pin 15 if the pulldown is an issue. I tried Serial printing all the pins digitalRead states from the arduino feather and i picked one that was in an off state so that it would be hot with 3.3v from the arduino when it fires the output on pin 8 when it meets the alarm triggered condition. Let me know if what Im sating is clear.

you can't determine the state of output pin with digitalRead. most of esp8266 pins are HIGH at power-up or boot

Im not trying to dertermine the state of the output pin with digital read. Im plan to fire the arduino uno on pin 8 as an output. From the that output will be hot at 5v. I take the 5 volts from the arduino board and step it down to 3.3v with a voltage regulator and two capcitors. Once I have that voltage I want to feed the output from the volatege regulator to then feed pin lets say 15 on the wifi module. Pin 15 on the wifi module would be an input. I want to determine the state of the input on the wifi module like this. I have already confirmed power all the to pin 15 and to negative

even though I read the voltage on my meter the state of the input will not change went i serial print the digital read value that is saved to a variable

I understand it but from here I can't say more that, that the input must be stronger then the pull-down. but it shouldn't be a problem, but the pull-down is strong (4.7kOhm. 10 kOhm is usual). try other pin.

Ok I understand. Im trying to understand your clue. Im not sure what you mean by pull down and 10kOHM is the usual. I just started working with arduino yesterday so I am not familiar with those terms or what I should be searching for online" I've been reading docs for several days to get it up to this point. I will try to see what I can find from what you expressed. Thanks

https://www.electronics-tutorials.ws/logic/pull-up-resistor.html

http://hyperphysics.phy-astr.gsu.edu/hbase/electric/watcir.html

Thank you very much. I understand what you mean now. This is very helpful. You're saying that I theres a high resistance on the pin and that my value is not being accurately translated. I will read this material and see if I can find for getting the pin back to a true state.

So im reading something about using input_pulldown or input_pullup to change the state. Does this sound familiar to you at all? Wondering if I am on the right track.

Hey thanks for your help yesterday. It helped a lot. Got me to the next step.


text:
AsyncWebServer giving wdt reset
I am using 3 Esp32 modules. One being master and other two being nodes.
Nodes are connecting to the master's AP. Master is connected with GSM module to execute the web api.
Master esp is having a Async Webserver which takes the http requests from the nodes and executes the appropriate web api. This web api returns the result and finally this result is sent back to the node as the response to the http request.
While running this code, Randomly on any request i face wdt reset.
Hence my question is, how should i handle the wdt resets and keep my program running softly.
E (32706) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
E (32706) task_wdt: - async_tcp (CPU 0/1)
E (32706) task_wdt: Tasks currently running:
E (32706) task_wdt: CPU 0: IDLE0
E (32706) task_wdt: CPU 1: async_tcp
E (32706) task_wdt: Aborting.
abort() was called at PC 0x400e1cc3 on core 0
Backtrace: 0x4008c434:0x3ffbe170 0x4008c665:0x3ffbe190 0x400e1cc3:0x3ffbe1b0 0x40084771:0x3ffbe1d0 0x4016aaf3:0x3ffbc0d0 0x400e307a:0x3ffbc0f0 0x4008a361:0x3ffbc110 0x40088b7d:0x3ffbc130

My Code Snippet is given below,
Master
HttpClient http(gsmClient, "www.mydummyserver.com", 80);
AsyncWebServer server(80);

const char* ssid = "ESP32-Access-Point";
const char* password = "123456789";
IPAddress ip(192,168,5,2);
IPAddress gateway(192,168,5,1);
IPAddress subnet(255,255,255,0);
const char* PARAM_MESSAGE = "message";

void notFound(AsyncWebServerRequest *request) {
    request->send(404, "text/plain", "Not found");
}

void setup() {

  Serial.begin(115200);
  WiFi.mode(WIFI_AP);
  delay(100);
  WiFi.softAPConfig(ip, gateway, subnet);
  WiFi.softAP(ssid, password);

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
        request->send(200, "text/plain", "Hello, world");
    });

 server.on("/myApi", HTTP_POST, [] (AsyncWebServerRequest *request) {

        String message;
        if (request->hasParam(PARAM_MESSAGE)) {
            message = request->getParam(PARAM_MESSAGE)->value();
        } else {
            message = "No message sent";
        }

        http.setTimeout(20000);
        String postData = "Param1=abcd&Param2=pqrs";
        http.beginRequest();
        http.post("http://www.mydummyserver.com/testapi.php");
        http.sendHeader("Content-Type", "application/x-www-form-urlencoded");
        http.sendHeader("Content-Length", postData.length());
        http.beginBody();
        http.print(postData);
        http.endRequest();
        int statusCode = http.responseStatusCode();
        String response = http.responseBody();

        Serial.print("Status code: ");
        Serial.println(statusCode);
        Serial.print("Response: ");
        Serial.println(response);
        request->send(200, "text/plain", "Response: " + message);

    });

 server.onNotFound(notFound);

    server.begin();

}

void loop() {

}

Node
HTTPClient httpClient;

void setup() {

  Serial.begin(115200);

  WiFi.begin("ESP32-Access-Point", "123456789");

  Serial.print("WiFi ");

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

  }

  Serial.println("connected:" + WiFi.SSID());

}

void executeApi() {

  Serial.println("Executing Api...");

  httpClient.setTimeout(20000);
  httpClient.begin("http://192.168.5.2/myApi");
  httpClient.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
  String contentStr = "Param1=abcd&Param2=pqrs";

  int httpResponseCode = httpClient.POST(contentStr);

  Serial.print("HTTP Response code: ");
  Serial.println(httpResponseCode);

  httpClient.end();

}

String cmd = "";
void loop() {

  if (Serial.available() > 0) {

    cmd = (Serial.readStringUntil('\n'));

    if (cmd.length() > 0) {

      if (cmd == "api") {
        executeApi();

      }

    }

  }

}

For sulutions i have tried following things,
a. I tried to write this into the loop() function.
 while(true){
   delay(1);
 }

b. Tried disabling the wdt
disableCore0WDT()
disableCore1WDT()

but none of these giving good results.

How do you wire the GSM module with the master, I don't see any code in your master related to configure or setup for communicating with the GSM. Is there any reason your node url endpoint is testapi, while it does not exist on your master's route (your master has a route handler for endpoint myApi. is your node connecting to web server directly instead of the master (which is a relay/proxy server).

@hcheung Hi, Due to privacy issues i could not share the real data.
GSM module and ESP are connected using HardwareSerial. I have corrected the code mistake for url endpoints. My node is connecting to master first and then it is executing remote server apis.

The following recommendations, as you aren't providing enough relevant info:

Install ESP-exception decoder and analyse your backtrace - Post it here so we can see in detail what caused the wdt
AsyncWebServer tends to cause this behavior if a response takes too long; a well placed yield() sometimes helps to prevent this behavior - to analyse you need ESP-exeption decoder
As loop() is running on core1 some/no process (idle) on core0 can cause the behavior. You can look up "task assignment to cores" on how to manually distribute the tasks (or send a yield() timed to core0 to reset the wdt)
Placing time-outs in combination with sleep/deep sleep (although you don't seem to use them) are also causes for wdt resets
A hackey trick is to set CONFIG_ASYNC_TCP_USE_WDT 0, but it is OK for testing

If you look into async_tcp for the possible culprit you see one line xTaskCreateUniversal(_async_service_task, "async_tcp", 8192 * 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE);
Here is an example of how I use it to prevent wdt resets. Place in setup():
disableCore0WDT();
disableCore1WDT();
disableLoopWDT(); // You forgot this one !

and because of this routine in the async_tcp lib:
static void _async_service_task(void *pvParameters) {
  lwip_event_packet_t * packet = NULL;
  for (;;) {
    if (_get_async_event(&packet)) {
      #if CONFIG_ASYNC_TCP_USE_WDT
      if (esp_task_wdt_add(NULL) != ESP_OK) {
        log_e("Failed to add async task to WDT");
      }
      #endif
      _handle_async_event(packet);
      #if CONFIG_ASYNC_TCP_USE_WDT
      if (esp_task_wdt_delete(NULL) != ESP_OK) {
        log_e("Failed to remove loop task from WDT");
      }
      #endif
    }
  }
  vTaskDelete(NULL);
  _async_service_task_handle = NULL;
}

I set the `CONFIG_ASYNC_TCP_USE_WDT 0` and it works so far.

Hi .. thanks for the detailed suggestion. i tried this too but still the same error happening, Can u guide me more ?

also when i paste the following error i have mentioned in questions does in exception decoder it prints nothing.. I guess the exception clearly states the issue without any traces.

You have to paste the part starting after Backtrace: ==>0x4 to the end into thedecoderits not possible to hve nothing, So the sequence is compile and upload, serial moiitor wait till error copy & paste backtrace ESP decoder -> copy result THAN post to your question (edit!) Thanks

Hi . I have pasted in question what my serial monitor is showing. Other than this no other error data serial monitor is showing.

IF YOU WANT HELP I need what I posted above you have to do it in your environment as I can not decode the backtrace without your elf file and all your settings/libs/path/version etc - please help me to help you

Short answer
increase the size of the _async_queue in AsyncTCP.cpp
_async_queue = xQueueCreate(32, sizeof(lwip_event_packet_t *));

from 32 to 64 or even higher if you can spare the space
Detailed (but possibly incorrect) explanation:
After looking at the OS calls, I found that in AsyncTCP.cpp
The event queue is created as:
_async_queue = xQueueCreate(32, sizeof(lwip_event_packet_t *));

Later the items are added with a Timeout of portMAX_DELAY, for example:
static inline bool _send_async_event(lwip_event_packet_t ** e){
    return _async_queue && xQueueSend(_async_queue, e, portMAX_DELAY) == pdPASS;
}

Since (at least when using the AsyncWebserver), both the queueing and the dequeuing are done on the same task (async_tcp), as soon as there are 32 events in the queue the moment the next event is to be added, the task will block indefinitely, causing the TWDT to be triggered.
So the solution might be to have the event queueing/dequeueing done in different tasks (maybe intended, since it already is an os queue) or increase the queue size to a value that will not be reached. Since the queue items are not that large, I just increased it to 256 to be on the safe side.
I am not sure if this explanation is correct, since I can't find the code where async_tcp feeds or kicks the watchdog during normal operation. So if someone knows how it works and could tell me, it would be greatly appreciated.

Thanks PiffPoff, increasing the queue size to 256 in AsyncTCP.cpp helped a lot getting rid of error below :

E (705728) task_wdt: Task watchdog got triggered. The following tasks
did not reset the watchdog in time: E (705728) task_wdt: - async_tcp
(CPU 0/1) AsyncTCP.cpp
_async_queue = xQueueCreate(256, sizeof(lwip_event_packet_t *)); Configuration
ESP32-S3 8Mb PSRAM 16Mb Flash
Arduino IDE
arduino-esp32 core 2.0.8
Wifi mode : Access Point


text:
Please explain the void loop() section of the sketch
#include <VirtualWire.h>

int PWMB = 5; //Speed control

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

  //receiver setup
  vw_set_rx_pin(2);
  vw_set_ptt_inverted(true);
  vw_setup(2000);
  vw_rx_start();
}

void loop(){
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;
  if (vw_get_message(buf, &buflen)) // Non-blocking
  {
    int i;
    int column = 0;
    String message;
    int commands[30];

    for (i = 0; i < buflen; i++)
    {
      //DEBUG:
      Serial.print(char(buf[i]));

      if(char(buf[i]) == '|'){
        commands[column] = message.toInt();
        message = "";
        column++;
      } else {
        message += char(buf[i]);
      }
    }

  commands[column] = message.toInt();
  }
}

This topic is the receiver side of my last topic: please explain the sketch attached
that one sending date and this is a receiver.
questions:

The transmitter transfer date array of [60] like: 523 | 487, here int commands[30]; just 30, is it OK?
if(char(buf[i]) == '|') / commands[column] = message.toInt();, seems just convert the date before '|'?
What is the result of message += char(buf[i]);?

Thanks

The transmitter transfer date array of [60] like: 523 | 487, here " int commands[30];" just 30, is it OK?

If you have a maximum of 59 characters (59 printable characters plus the NULL at the end equals 60), and each number is separated by a | character, then the maximum possible numbers you can have, if they are all single digit, is 30. So yes, an array of 30 integers is fine.

" if(char(buf[i]) == '|') / commands[column] = message.toInt();", seems just convert the date before '|'?

Yes. It takes whatever has been placed in message and converts it to an integer, then empties message ready for the next number.

what is the result of " message += char(buf[i]);"? Thanks

It adds the current character from the buffer (pointed to by i) to the end of the message string.
It's not the best way of doing it, and it can make a mess of your heap causing your Arduino to crash after a while.
Personally I would use strtok() directly on the buffer:
int i = 0;
char *part = strtok(buffer, "|");
while (part) {
    command[i] = atoi(part);
    i++;
    part = strtok(NULL, "|");
}

This of course assumes that buffer is properly NULL terminated.

@ Majenko♦ Thank you Majenko♦, would you please ref to: https://arduino.stackexchange.com/questions/62576/please-explain-the-sketch-attached/62579?noredirect=1#comment134324_62579 and see what's the date sent? and see if there are match?