text:
How can I get additional Slave Select pins?
I have a project where I want to connect a number of SPI devices, and I'm running out of Slave Select pins (SPI) on the Arduino. So I thought that I could use something like an MCP23S17 to get additional pins and use those as SS pins, but most libraries require to pass the pins when initialising, and it seems that I can't pass the MCP's pins as a function/class argument (or can I?). For example:
U8G2_SSD1306_128X64_NONAME_F_4W_HW_SPI u8g2(U8G2_R0, /*cs*/ 12, /*dc*/ 4, /*rst*/ 6);

So my question is: How can I get more SS pins? Thank you

The problem with your plan is... how do you arrange to only have one SS pin active at once? You turn one of the expander pins on - that SS is then active. However you need a different SS active to turn it off again. You have a bit of a catch-22 situation: you need to turn off the SS pin in order to turn off the SS pin. The only reliable way is to have a second SPI bus that controls the expander.

True. What if I use the i2c MCP23017 though? In which case the SS pins would be controlled through i2c... That's my current scenario, but it doesn't solve the issue of putting the MCP's pins into library function calls.

That would fix it - basically using a second bus (and changing the protocol but that's irrelevant).

And how would I pass the SS pins on an MCP23017 as arguments to the libraries after that?

You wouldn't. Not without lots of nasty hacks.

If you're using an Uno or similar, have you looked at a Mega? It has more Digital Outputs but you'd want to confirm the SPI library supports the additional Mega outputs (I've never used one personally).

I would suggest adding a layer of abstraction in your whole design.
Use the ESP8266 as the main system controller, then farm out sensor communications to one or more other "active" expansion devices.
Rather than just using an expander for the SS pins you are using the "expander" for all the communication.
By "expander" I basically mean some other microcontroller (maybe an ATMega328P for example) which receives an instruction to sample a sensor then goes off and gathers the data that is wanted and sends it back to the master ESP8266 controller.
How you arrange that communication is up to you, but maybe I2C would be a good way to go.  You could even make the sensor data gathering completely autonomous so that the ESP8266 just then requests the latest data from the slave(s).
It means:

You don't have to change any libraries
You get distributed processing, sharing the work out
The ability to communicate with an almost infinite number of sensors

I assume you're right and this is the best solution, but I would prefer to have only one controller chip. Otherwise it means I have to write 2 programs, one for the ESP8266 and one for the sensor communication controller. Is there any way to avoid that?

Use a bigger controller with more pins. It is very common to build a system with multiple controllers in it.

Ok, assuming I use something like an ATMega328P, how would I update its firmware then if it is merely a slave of the ESP8266?

The same way you would in any other situation. Just because it is connected to an esp8266 makes no difference.

My solution would be to keep it simple. Use real pins for every SPI SS. Buy an other Arduino board with more pins if you need more pins.
What else is connected to your Arduino board ? Perhaps it is easier to reduce those pins. Almost all analog pins can be digital pins as well. You could use external ADC modules. Perhaps replacing 1-Wire or DHT11 or DTH22 with I2C sensors. Using a I2C display. There are many options to use buttons and leds with a few pins. And so on.

I'm actually using an ESP8266 (in the arduino environment), so my pins are rather limited.

The ESP32 has solved all the disadvantages of the ESP8266. For example the Sparkfun Thing https://learn.sparkfun.com/tutorials/esp32-thing-hookup-guide has 32 pins.

A maybe dirty solution is to change all the libraries. Everywhere the SS pin is used, instead call a function and set it yourself (by using the MCP23S17).
To make this a bit better, define a class that contains this functionality to abstract it from the changed library classes.
Example:
As initialization of the library a function or class constructor will be used, e.g.
MCP23S17(void);

This you will use like:
MCP23S17 my_component = MCP23S17();

You need to change this to:
MCP23S17(int ss_pin);

And change the related code, store it in a class variable and use it everywhere in the library instead of the fixed SS pin number.
Than you can constructor your own instance by:
MCP23S17 my_component = MCP23S17(4);

Where 4 is the SS pin number

That is a possibility, but a bit of a difficult one and not very efficient. I mean if any library upgrades, I have an issue...

Yes completely true, it's quite dirty to change libraries anyway (but a literal ' solution' ) ... on the other hand, if you change the libraries and make the SS pins flexible everybody can use it (and it could be the new 'default' libraries). Actually I don't understand why people making libraries do not implement flexible pin assignments anyway directly from the start.

Can you give me an example of what that could look like?

I updated my answer

I saw. I'm trying to understand it.


text:
where does access point's IP address come from for sketch AP_SimpleWebServer.ino in Github WiFi101 examples
I don't understand where the access point's IP comes from.
Sketch uses WiFi.beginAP( ssid )   ..to start the AP.
Then, printWifiStatus() gets the access point's IP with:
IPAddress ip = WiFi.localIP();

How does .beginAP() create the IP?  What does it use for a mask?
I'm creating network service on a MKR1000, and want to use .beginAP() to make it an access point, so I don't need a "middle man" (router).  Going to have mobile device (iPhone) connect directly to Arduino MKR1000.

If you look into that github source code, you can see startAP function and mainly rows with strM2MAPConfig.au8DHCPServerIP:
uint8_t WiFiClass::startAP(const char *ssid, uint8_t u8SecType, const void *pvAuthInfo, uint8_t channel)
{
    tstrM2MAPConfig strM2MAPConfig;

    if (!_init) {
        init();
    }

    if (channel == 0) {
        channel = 1; // channel 1 is the minium channel
    }

    // Enter Access Point mode:
    memset(&strM2MAPConfig, 0x00, sizeof(tstrM2MAPConfig));
    strcpy((char *)&strM2MAPConfig.au8SSID, ssid);
    strM2MAPConfig.u8ListenChannel = channel - 1;
    strM2MAPConfig.u8SecType = u8SecType;
    strM2MAPConfig.au8DHCPServerIP[0] = 0xC0; /* 192 */
    strM2MAPConfig.au8DHCPServerIP[1] = 0xA8; /* 168 */
    strM2MAPConfig.au8DHCPServerIP[2] = 0x01; /* 1 */
    strM2MAPConfig.au8DHCPServerIP[3] = 0x01; /* 1 */

    if (u8SecType == M2M_WIFI_SEC_WEP) {
        tstrM2mWifiWepParams* wep_params = (tstrM2mWifiWepParams*)pvAuthInfo;

        strM2MAPConfig.u8KeyIndx = wep_params->u8KeyIndx;
        strM2MAPConfig.u8KeySz = wep_params->u8KeySz;
        strcpy((char*)strM2MAPConfig.au8WepKey, (char *)wep_params->au8WepKey);
    }

    if (m2m_wifi_enable_ap(&strM2MAPConfig) < 0) {
        _status = WL_CONNECT_FAILED;
        return _status;
    }
    _status = WL_AP_LISTENING;
    _mode = WL_AP_MODE;

    memset(_ssid, 0, M2M_MAX_SSID_LEN);
    memcpy(_ssid, ssid, strlen(ssid));
    m2m_memcpy((uint8 *)&_localip, (uint8 *)&strM2MAPConfig.au8DHCPServerIP[0], 4);
    _submask = 0x00FFFFFF;
    _gateway = _localip;

    // WiFi led ON (rev A then rev B).
    m2m_periph_gpio_set_val(M2M_PERIPH_GPIO15, 0);
    m2m_periph_gpio_set_val(M2M_PERIPH_GPIO4, 0);

    return _status;
}

Ah, hah!   192.168.1.1    Look at the code:  I feel sheepish. I'm still getting used to EVERYTHING being available with open source, I guess.  Thanks!

source: Stack Exchange

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

sort: votes


text:
Data transfer using SPI
Sorry for my code is long and my English is not good.
I'm working with 8x8x8 LED cube project using Arduino nano. I tried to understand code, but I don't understand how cube[][] data write on pins.
I just want to know, how write the data from cube[8][8] to hardware using SPI. code download using this link.
Thanks in advance.
My code is here :
#define AXIS_X 1
#define AXIS_Y 2
#define AXIS_Z 3
#define REFRESH_RATE 120

int CUBE_SIZE = 8;
int SPI_CS = 10;// This SPI Chip Select pin controls the MAX72xx
byte value[8];

volatile unsigned char cube[8][8];
volatile int current_layer = 0;

void setup()
{
  Serial.begin (115200);
  Serial.println("jolliFactory 8x8x8 jolliCube Demo example 1.0");

  pinMode(SPI_CS, OUTPUT);

  SPI.begin();

  maxTransferAll(0x0F, 0x00);   // 00 - Turn off Test mode
  maxTransferAll(0x09, 0x00);   // Register 09 - BCD Decoding  // 0 = No decoding
  maxTransferAll(0x0B, 0x07);   // Register B - Scan limit 1-7  // 7 = All LEDS
  maxTransferAll(0x0C, 0x01);   // 01 = on 00 = Power saving mode or shutdown
  maxTransferAll(0x0A, 0x0F);   // Set Brightness Intensity

  setUpInterrupts();
}

// Get the current status of a voxel
unsigned char getvoxel(int x, int y, int z)
{
    if (inrange(x,y,z))
    {
        if (cube[z][y] & (1 << x))
        {
            return 0x01;
        } else
        {
            return 0x00;
        }
    } else
    {
        return 0x00;
    }
}

void maxTransferAll(uint8_t address, uint8_t value)
{
  digitalWrite(SPI_CS, LOW);

    for ( int c=1; c<= CUBE_SIZE;c++) {
        SPI.transfer(address);
        SPI.transfer(value);
    }

  digitalWrite(SPI_CS, HIGH);
}

void maxTransferOne(uint8_t whichMax, uint8_t address, uint8_t value)
{
  byte noop_reg = 0x00;    //max72xx No op register
  byte noop_value = 0x00;  //value

  digitalWrite(SPI_CS, LOW);

  for (int i=CUBE_SIZE; i>0; i--)   // Loop through our number of Max72xx ICs
  {
    if (i==whichMax)
    {
      SPI.transfer(address);
      SPI.transfer(value);
    }
    else
    {
      SPI.transfer(noop_reg);
      SPI.transfer(noop_value);
    }
  }

  digitalWrite(SPI_CS, HIGH);
}

void maxTransferLEDCube(uint8_t address)
{
  digitalWrite(SPI_CS, LOW);

  for (int i=0; i<CUBE_SIZE; i++)   // Loop through our number of Max72xx ICs
  {
      SPI.transfer(address);
      SPI.transfer(value[CUBE_SIZE-i-1]);
  }

  digitalWrite(SPI_CS, HIGH);
}

void setUpInterrupts()
{
  cli();//stop interrupts while we set them up
  //set up an interrupt with timer1
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;
  OCR1A = (16000000/REFRESH_RATE/1024/CUBE_SIZE -1);
  TCCR1B |= (1 << WGM12);
  // Set to CS10 and CS12 so we have the 1024
  TCCR1B |= (1 << CS12) | (1 << CS10);
  TIMSK1 |= (1 << OCIE1A);
  sei();//re-allow interrupts
}

ISR(TIMER1_COMPA_vect)
{
  for(byte y = 0 ; y < CUBE_SIZE ; y++)
  {
    byte b = 0;

    for(byte x = 0 ; x < CUBE_SIZE ; x++)
    {
      //form data byte
      b = b << 1;

      if (getvoxel(x,y,current_layer)==1)
      {
        b |= 1;
      }
    }
        value[y] = b;
  }

  maxTransferLEDCube(CUBE_SIZE - current_layer);

  current_layer++;

  if (current_layer == 8)
    current_layer = 0;
}

First, you need to know how the LEDs are arranged. There are 8 layers, each with 8 rows, each with 8 LEDs.
Each LED is represented as a single bit inside unsigned char cube[8][8]; - the first [8] is the array of layers, the second [8] is the array of rows, and the unsigned char holds 8 bits to represent the state of the 8 LEDs in that row.
Each LED layer has one MAX7219 8x8 LED Matrix Controller. To tell it what to do you need to give it a Command byte and a Data byte. So to tell it to light up LEDs 1, 2, and 7 on the fourth row, you need to tell it 0x04 0x86. You send this command by setting CS LOW, sending the 16 bits of the Command+Data, then setting CS HIGH.
Each MAX7219 is connected one after the other in an SPI string. To command all of them at once you need to set CS LOW, send 16 bits for each MAX7219 (128 bits in all), then set CS HIGH. If you only want to command one MAX7219, you need to send a NOP Command+Data (0x00 0x00) to all the others.
The way the program works is:

setup()
a. Initialise the Serial port, and print a message.
b. Set the CS pin as an OUTPUT, then initialise SPI.
c. Initialise all the MAX7219 chips by sending a series of commands -
the same Command+Data to each of them (maxTransferAll()).
d. Initialise the Timer interrupt (setUpInterrupts()).
loop()
This isn't shown in the code. Presumably it alters the cube[8][8] array to make the special effects.
TIMER1_COMPA_vect (the interrupt handler)
Every time the timer ticks, the handler will command all of the MAX7219s to show the next row of LEDs.  This will last until the next timer tick, when the next row will be displayed. If this is done fast enough, the human eye's "persistence of vision" will not see the rows flickering.
For each row (`y`) in the `cube` array
   Set `b` to 0
   For each bit ('x') in the `cube` data
      If the bit is set (`getvoxel(...)`) set a bit in `b`.
   Store `b` in the `value[y]` array

value now holds the bytes needed as Data for the next row for each of the MAX7219 chips.
    Send value over SPI using `maxTransferLEDCube(...)`

Since the cube displays the same row for each layer simultaneously, the Command doesn't have to change, only the Data does. That's what the value array holds: the Data to be sent to each MAX7219 chip.

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


text:
How to determine minimum and maximum angle for cheap servos?
I have some cheap KY66 (seems to be SG90 clone) servos.
When I turn them to 0°, the servo tries moving and moving, without actually getting to 0°. I read that they are reaching the endpoint but the built-in potentiometer does give a reading of 0.
By changing the code and fiddling with the angle, I find that the minimum for one particular servo is 25°.
I'm now trying to figure out how the Arduino could determine this value automatically. I have tried
servo.write(0);
delay(3000);
int direction = servo.read();

and expected to get back a value near 25, but it was 0 instead. So the result of read() does not seem to be an actual reading, but more the "last known" setpoint.
I've also tried to relax the servo before reading:
servo.write(0);
delay(3000);
int direction = servo.read();

with no better result.
I like to figure out the minimum and maximum angle of the servo

because I don't like the servo to make much noise (it really doesn't sound healthy)
without having the user to figure out by himself and the need of re-programming the Arduino.

I know that these cheap servos only have 3 pins. 2 pins are for power supply only, so there's only 1 pin left.
My questions:

Is the data pin uni-directional (PWM output from Arduino to servo)?
Will it ever be possible to implement what I want without additional hardware?
How do people solve this issue? Do more expensive servos either have better calibration to actually go from 0° to 180° or do they provide a way to read the potentiometer with another pin?

Is the data pin uni-directional (PWM output from Arduino to servo)?

As you found out, standard servos have only three pins. And yes, two of them provide ground and power, and the third is a unidirectional signal.
This signal is commonly a pulse of 1 ms to 2 ms, repeated every 20 ms.
servo.read() can therefore only return the last value set by servo.write().

Will it ever be possible to implement what I want without additional hardware?

I don't think so.
You could insert a shunt into the power line and measure the current. If it stays high for extended periods, it means that the servo is still powering its motor. But this could be true also for other reasons than being at its own mechanical limit.

How do people solve this issue? Do more expensive servos either have better calibration to actually go from 0° to 180° or do they provide a way to read the potentiometer with another pin?

Since servos are used as a closed (sub-)system, I don't think that they are opened to read their potentiometer. And even if you do this, you might affect the internal working of the servo.
Eventhough I built several model aircrafts since the late 70s and used different servos, I have no feeling about the calibration of cheap or expensive servos. IIRC some data sheet documented ranges of only +/- 45°.
So the values 0 to 180 for servo.write() is just a mapping for 1 ms to 2 ms.
To make a long story short, I have no idea how people solve this.
You might like to limit your range to some "healthy" values, or ask the user to help in calibration. The calibration results can be stored in EEPROM, there is no need to reprogram the Arduino.
If you need the robot's head to turn from 0° to 180°, consider using some gear so that the servo just needs to move between, let's say, 30° to 150°. This is the way modellers go.

I think you have 2 choices: either measure and store for each one individually, or find the worst case for all of them and code around that.
Do you really need the full travel? If you're using the servo to push/pull, the servo-travel endpoints are pretty weak anyway.

I wanted a robot look left and look right, which is 0° or 180°.

Maybe you can make up the limited angular travel of the servo in the linkage between the it and the camera platform.

Indeed I wanted a robot look left and look right, which is 0° or 180°. 25° is quite a bit off. But well, it seems I need to consider that.

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


text:
Missing ACKs on I²C
I am using a GY-521 accelerometer as well as BMP280 pressure sensors via I²C on an ESP8266.
When I analyze I²C data with the oscilloscope, I can see missing ACKs on both of them as shown in the pictures.
Is that something to worry about or is it just normal, considering I bought cheap Chinese sensors?

My BMP280 code is this:
// https://github.com/mahfuz195/BMP280-arduino-library
#include <BMP280.h>
BMP280 bmp280;

#include "Wire.h"
TwoWire i2c = TwoWire();

// Hardware setup
#define CLOCK_PIN D1
#define DATA_PIN D2
#define I2C_SPEED 400000

// I²C response codes
#define FOUND 0
#define NORESPONSE 2

bool sensorAvailableAt(byte address)
{
   i2c.beginTransmission(address);
   byte response = i2c.endTransmission();
   return response == FOUND;
}

void stop(char* message){
  Serial.println(message);
  while(true);
}

void setup() {
  Serial.begin(115200);
  while(!Serial){} // Waiting for serial connection

  i2c.begin(DATA_PIN, CLOCK_PIN, I2C_SPEED);
  if (!sensorAvailableAt(0x76))
  {
    stop("BMP280 sensor not found");
  }

  if (bmp280.begin())
  {
    Serial.println("BMP280 init success");
  }
  else
  {
    stop("BMP280 initialization failed.");
  }
}

void loop() {
  double temperature;
  double pressure;
  bmp280.getTemperatureAndPressure(temperature, pressure);
  double sealevel = bmp280.sealevel(pressure, 800);

  Serial.print("Temperature: ");
  Serial.print(temperature,1);
  Serial.println(" °C");

  Serial.print("Pressure: ");
  Serial.print(pressure, 1);
  Serial.println(" mbar (absolute)");

  Serial.print("Pressure: ");
  Serial.print(sealevel);
  Serial.println(" mbar (sealevel, compensated for 800 m height)");

  delay(50);
}

I'm not sure, how the images are to be interpeted. A NACK at the end of the transmission (before the stop condition) is normal and belongs to the I2C protocol. The master signals that way, that it does not want to read more data.

@chrisl: ah, that's valuable. I'll try to find more on that

Can you confirm, that the "missing ACK"/NACK happens on the end of every master read action? If yes, I will formulate that as an answer.

@chrisl: yes, that's what I see and how I interpret the data. Do I get it right that this should only happen with a dedicated sensor library, where the implementation knows how much data to expect? In case of a more generic I²C implementation, the master would not know how much data there is to read and thus would not stop the transmission?

The NACK at the end of a master read/slave send transmission is normal expected behavior.
In I2C communication the acknowledgement is a possibility to react to send data. For example, when the slave sends a NACK while the master sends data to it, it might be, because it currently cannot process further data. Acknowledgement goes in both ways, depending on the direction of transmission. The reader always needs to acknowledge the data to mark a successful transmission. It is normal for the master to send a NACK on the end of it's reading cycle to mark, that it doesn't want to receive more data. While this isn't strictly logically needed (since the end of a transmission is marked by the master by a STOP or RESTART condition), it is done nonetheless.
I think I have also seen this behavior with the Wire library of Arduino. So it comes down to the implementation of the I2C protocol in your case. As your library simply uses the Wire library, the behavior is not part of it. The I2C protocol is implemented by Wire. You would see the same behavior in every sensor library, that uses the Wire library.
You can read more about the I2C protocol at this site.

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


text:
RCSwitch on Attiny85
I would like to use my Attiny85 as an remote controlled relay switch.
I have already tested the sketch on my Atmega328 and it worked.
Now I wanted to burn the sketch on my Attiny85 using ArduinoISP but I get the following error in the ArduinoIDE:
sketch_dec25a.ino: In function ‘void setup()’:
sketch_dec25a:13: error: ‘class RCSwitch’ has no member named ‘enableReceive’
sketch_dec25a.ino: In function ‘void loop()’:
sketch_dec25a:20: error: ‘class RCSwitch’ has no member named ‘available’
sketch_dec25a:21: error: ‘class RCSwitch’ has no member named ‘getReceivedValue’
sketch_dec25a:22: error: ‘class RCSwitch’ has no member named ‘getReceivedValue’
sketch_dec25a:25: error: ‘class RCSwitch’ has no member named ‘resetAvailable’

That's my code:
#include <SoftwareSerial.h>
#include <RCSwitch.h>

int RELAY_PIN = 2;

RCSwitch mySwitch = RCSwitch();
SoftwareSerial mySerial(1, 3); // RX, TX

void setup()
{
  pinMode(RELAY_PIN, OUTPUT);
  mySwitch.enableReceive(0);  // Receiver on inerrupt 0 => that is pin #2
  mySerial.begin(9600);
  mySerial.println("Hello, world?");
}

void loop() // run over and over
{
  if (mySwitch.available()) {
    Serial.println(mySwitch.getReceivedValue());
    if(mySwitch.getReceivedValue() == 1234567){
      digitalWrite(RELAY_PIN, HIGH);
    }
    mySwitch.resetAvailable();
  }
}

I am using these cores: https://code.google.com/p/arduino-tiny/
I am using the SoftwareSerial just for debugging.
Sorry for my bad english and thanks for your help!

The issue you face is that RCSwitch does not seem to support receive mode for ATtiny.
This is what you can find in RCSwitch.h:
// At least for the ATTiny X4/X5, receiving has to be disabled due to
// missing libm depencies (udivmodhi4)
#if defined( __AVR_ATtinyX5__ ) or defined ( __AVR_ATtinyX4__ )
#define RCSwitchDisableReceiving
#endif

Then all methods related to receptions are not defined in RCSwitch class for ATtiny MCUs:
#if not defined( RCSwitchDisableReceiving )
void enableReceive(int interrupt);
void enableReceive();
void disableReceive();
bool available();
void resetAvailable();

unsigned long getReceivedValue();
unsigned int getReceivedBitlength();
unsigned int getReceivedDelay();
unsigned int getReceivedProtocol();
unsigned int* getReceivedRawdata();
#endif

I am really not sure if there is a way to work around it, I have not looked at the code in RCSwitch.cpp.
Maybe you best option would be to find another RC library.
For instance, if you can use Infra-Red RC, then there are libraries out there that could work for ATtiny:
https://github.com/shirriff/Arduino-IRremote

Arduino-IRremote is not compatible with ATTiny as well.

According to this issue https://github.com/shirriff/Arduino-IRremote/issues/97 it seems there are some options for ATtiny.

I have tested with Digispark ATtiny85 and https://github.com/sui77/rc-switch work perfect
just comment #define RCSwitchDisableReceiving
than use in setup code enableReceive(0); and external pin 7 PB2(int0) as RF source
Or you can use other software pin interrupt
in setup:
PCMSK |= (1<<PCINT0);//here pin number
GIMSK |= (1<<PCIE);
interrupt function

ISR(PCINT0_vect) {
  rd.handleInterrupt(); // you need also put handleInterrupt() in public section in RCSwitch.h
}

Yes, as akaJes addition working great!
I move handleInterrupt() do public in RCSwitch.h, comment #define RCSwitchDisableReceiving and adding interrupt function like akaJes. Thanks! :-)


text:
Extract arduino collected data periodically
I'd like to extract data collected by a battery powered arduino for example once a day without stopping it and not using SD card.
It's posible, when I want to extract the collected data, to connect a laptop through the USB and then get data because Arduino is, at regulat time intervals, calling 'Serial.println(...)'?

What do you need help with exactly?

Please be aware thqt most Arduino models will reboot when you plug a cable to the USB port and have your PC open communication. This may not be what you want as all data stored in SRAM will be lost.

Would you consider having a second arduino to collect the data wirelessly? This second. Arduino could be connected to a computer collecting the data. Asking since I'm not sure if the solution absolutely can only include a single arduino.

This is a bit crude, but I think you could use an FTDI cable (which is a USB to UART converter) to have a program in your laptop talk to the Arduino using its UART (serial) interface.
To do it, you could plug the USB side of a FTDI serial cable to your laptop. The other end of the cable has a plug with 6 pins, 2 of which are the TX and RX serial signals. You could plug those two signals to pins D0 and D1 (RX & TX) of your Arduino using male-to-male jumpers.
In terms of software, you could code the Arduino sketch to listen on the serial port for a command from your laptop. When the command arrives, it would output the stored data (could be comma separated values with CR+LF as end of line). Your laptop would then listen for the answer and retrieve the data.

Yes, you can do it. Depends how much data to have enough storage space. You also need consider potential memory endurance. E.g. external I2C ferromagnetic memory is good option. Of course it's not on Arduino board, you implement extension.


text:
NodeMCU access point for MQTT broker
Is it possible to publish and subscribe using MQTT, when the mqtt broker is connected to a network which is created by a NodeMCU?
Can a NodeMCU connect to its own created network?

Don't cross post.. You already asked this on SO.

no, there's no broker that runs on arduino.


text:
AtTiny44 and AtTiny 85 communication
I'm working on a project where I use two microcontrollers: an AtTiny44 (20MHz ext clock) and an AtTiny85 (8MHz internal).
What I'm trying to achieve is an I2C communication between the 85 and the 44, with the 44 acting as master and the 85 as slave, then transmit the data read from both of them to a PC with FDTI cable using softwareSerial.
I started with writing the AtTiny85 code:
   #include <TinyWireS.h>
   #define ADC3 A3

   void setup() {
      TinyWireS.begin(I2C_SLAVE_ADDRESS); // join i2c network
      TinyWireS.onRequest(requestEvent);
      pinMode(4,OUTPUT);
      digitalWrite(4,HIGH);
      pinMode(ADC3,INPUT_PULLUP);
   }

   void loop() {
      // This needs to be here
      TinyWireS_stop_check();
   }

   // Gets called when the ATtiny receives an i2c request
   void requestEvent() {
     int val=analogRead(ADC3);
     byte valLow = val & 0xff;
     byte valHigh = (val >> 8);
     TinyWireS.send(valHigh);
     TinyWireS.send(valLow);
   }

With this I am able to send the data read from an adc (A3 pin) to an Arduino as 2 bytes
The Arduino code:
  #include <Wire.h>

  int check=0;

  void setup() {
     Wire.begin();        // join i2c bus (address optional for master)
     Serial.begin(9600);  // start serial for output
  }

  void loop() {
      Wire.requestFrom(8, 2);    // request 2 bytes from slave device #8

      while (Wire.available()&&check<2) { // slave may send less than
                                          // requested
        int c = Wire.read(); // receive a byte as int
        check++;
        int d = Wire.read();
        check++;
        int number = d | c << 8; //convert two bytes as int
        Serial.println(number);
     }
     check=0;
     delay(500);
   }

Maybe the check variable is useless, but it's not a problem, because I'm getting the right reading on serial monitor.
I then moved to the AtTiny44; I have an onboard thermistor, and I need to print on softwareSerial the value read from this and the value read from the AtTiny85 board.
This is the code, using TinyWireM:
  #include <TinyWireM.h>
  #include <USI_TWI_Master.h>
  #include <SoftwareSerial.h>

  SoftwareSerial mySerial(0, 1); // RX, TX

  int adc = 2;
  int check=0;

  void setup() {
    pinMode(1, OUTPUT);
    pinMode(0, INPUT);
    pinMode(4,INPUT_PULLUP);
    pinMode(6,INPUT_PULLUP);
    pinMode(7, OUTPUT);
    pinMode(adc, INPUT);
    mySerial.begin(9600);
    TinyWireM.begin();        // join i2c bus (address optional for master)
    while (!mySerial) {
      ;
    }
    mySerial.println("Serial comm started");
    digitalWrite(7, HIGH);
    delay(1000);
    digitalWrite(7, LOW);
 }

 void loop() {
   mySerial.println((int)analogRead(adc));
   TinyWireM.requestFrom(8, 2);    // request 2 bytes from slave device #8
   while (TinyWireM.available()&&check<2) { // slave may send less than
                                            // requested
   digitalWrite(7, HIGH);
   int c = TinyWireM.receive(); // receive a byte as character
   check++;
   int d = TinyWireM.receive();
   check++;
   int number = d | c << 8;
   mySerial.println(number);
   }
 check=0;
 delay(500);
 }

The softwareSerial is working good (I get to write the ADC data from the 44) but I can't find where the problem on I2C is (on console monitor mySerial.println(number) sends out 0).
What I excluded so far: connections error, clock skew (the clocks are distant between them), pull-up on I2c bus (they are high in both devices)

Why use I2C? Maybe other protocols could be faster/simpler/less pins for this use?

I don't think there are simpler protocol, or with less pin. I thought of using two softwareSerial but they can't work togheter at the same time

You data rate seems pretty low, and maybe you only need to send in one direction over the link between the two units? If so, maybe just a single signal wire and a ground between them. Sender drives the wire high for 1ms to signal a "0", 2ms to signal a "1". Really simple bit banged serial port.

I need to send data in only one way, yes. I'd like to use I2C, but I'm interested in your workaround. Can you point me to some hints? Also how can I manage the master requesting data to the slave in your solution?

Do you need to have the master request? Why not just have the slave always blindly sending?

It could also blindly send, but how I can manage the timings between the softwareSerial and the bit banged serial?

On the chip connected to the FDTI, make a pin change ISR for the piun that is connected to the data line coming from the remote. Everytime the pin changes low-to-high, save the current time. Everytime it changes high-to-low, look at the diff between current time and saved time. If time is ~1 second then received a 0 bit, if time is ~2 seconds then received a 1 bit. shift them into a holding variable until you have a byte of data. When you get it working, you can make much faster, but with 1 & 2 seconds easy to debug with an LED.

Perhaps the ATtiny85 can't handle the I2C clock rate being generated by the AtTiny44.  Try running them both at the same clock speed.

the 85 as slave

writing a slave, especially an i2c slave, isn't for the faint of heart. typically you use a state machine to help handle that.
one great example is the one presented by nxp in old LPC210x datasheet. AVRs share the same i2c hardware so it is immensely portable to the avr.

I know that, but the funny thing is that is the attiny44 master that is not working!


text:
Reading and processing a PWM on AtTiny45
I have this question and I can't find answers!
I wanted to use an AtTiny45V (due to low voltage requirements, it will run at 1.8 volts) to read a PWM from an Arduino, and then process this information.
Explained better:
let's say, I hook up one pin of the AtTiny to an Arduino pin (named connection), and in the IDE I write:
AnalogWrite(connection,X)

I want the AtTiny to write high on a port based on the X value.
Example:
X = 20 writes high on AtTiny PB5
X = 25 writes high on AtTiny PB5 and PB3
etc...
So, basically I want to read the duty cycle from the Arduino PWM and let the AtTiny do something based on duty cycle value.
Is this possible?
Thanks

I got the feeling that PWM isn't the best "protocol" for transmitting data. Why not use UART (serial)?

@Gerben I need to implement this "protocol" because I have to drive 6 AtTiny, I know it's not so suitable, it's just a workaround

What kind of data do you need to transmit? If you just need to send a short number,  you could just send that number of pulses, with a quite period after it. Very easy to read, no ambiguous readings, as it doesn't rely on very precise timing, like PWM (where you might send 120, but read 118 on the tiny, because of inaccuracies).

@Gerben That is not a problem, I have only 8 cases to choose (I have to switch 3 leds, basically I'm doing an RGB controller), so a big accuracy is not required (I could make in the if controlling on the input pin a +/-10 error tollerance).

You don't need to read the duty cycle, just the time that the PWM signal is high. First wait for the input pin to go high, then start a timer, wait for the signal to go low again, and finally read the timer value. If other tasks need to be performed concurrently then use pin change interrupt to detect the high and low transitions.
If the ATtiny is running Arduino software then the solution is even easier - just use the pulseIn() function.
This technique works for all PWM values except 0 and 255. With these values the pin stays low or high permanently, so there are no transitions to time. The easiest way around this is to simply avoid transmitting 0 or 255.
Alternatively you could pass the PWM signal through an RC filter to produce a 'DC' voltage, then read it with the ADC. However this will slow the response time down, and the signal will produce intermediate values as it goes from one voltage to another. To get good resolution the RC filter would need to have a long time constant, and you might have to average several readings to get a stable value.

Well, thanks. I'll try this as soon as possible, it should work

It's working like a charm. I marked only now because I had to mill the board and solder everything! If someone is interested I'm documenting this "PWM controller", just contact me.

If I understood correctly you want to drive a digital output on the AtTiny45V based on the PWM value from your Arduino, right?
I would suggest to use a simple low-pass RC filter to extract the mean value from the PWM and read as an analog voltage in the AtTiny45V. As the frequency of your PWM is known, you can easily design your filter to extract the mean value of your signal.
Then, based on your PWM mean value, you can define which pin will be set.


text:
HC-05 module short circuit
I have bought a HC05 bluetooth module and I think I accidentally short circuited it. Is there any way to change the voltage regulator or methods to reuse it again?

I suppose you're referring to the HC05 module, already soldered on a board, with the 6-pin header. The regulator is on that board.
Online you'll find several versions of that board, therefore you should check the schematics, to find which you need to mount. For instance, on some board, a R1114-33 is used.
Changing the regulator is not the hardest task on earth, however, other components are very close to it (capacitors).
Still there are 2 things to consider:

Is it worthy to change the regulator? That module will cost few
bucks.
As you can see from the datasheet, the regulator is short-circuit protected (yes, it does not mean that it will be indestructible). I think, instead, you destroyed one of the two ICs of the bluetooth module soldered on board. And those one, beside of being quite difficult to find and expensive in small quantity, they are very hard do replace.

Thank you for your comment sir. I have already lost 2 of them due t short circuit issue ,which is really frustrating .So instead of buying I wanted to fix it. Is there any way to know if the Bluetooth ICs are destroyed?

@curious-boy do they heat up? If yes, they are dead. If not, this does not mean that they aren't... How and where did you short circuit the module? I.e. which pin?

yes they heat up .I guess i have to buy a new one.

I think that this has been caused by:

accidentally a wire (powered at 5V) contacted one of the various solder joints of your board. (always turn off power when mounting the circuit!) 2) maybe you should consider to put a resistor in series to the TXD and RXD lines (yes, many modules already have them, but in some of them they are just 100 Ohm! too low for a 5V to 3.3V conversion! Put 10k  if you're going up to 115200).

To be sure: you didn't connect that module to a serial port of a PC, right? The serial port outputs up to 12V on the RXD and TXD lines...


text:
Is it possible to use Serial window for debug statements while using the hardware serial port for GPS module?
I am using the hardware serial ports of Atmega 328 to connect to a GPS module . A GSM SIM900 module is connected via Software serial . Is it possible to print the debug statements in the Serial window while the GPS module is connected to the hardware serial ports? Both my module and the Serial window is set to 9600 bps baud rate .
Also I want to read the GSM responses from the Software serial and print the same in the Serial window for debugging. Is this possible?

I am using the following statements for the latter function:

I am using the following statements for printing the GSM responses :  Serial.print (softserial.read()) . Is this possible while I am connecting GPS module to the hardware serial ports?

You can edit your question. No need to add additional info into the comments.

Is it possible to print the debug statements in the Serial window while the GPS module is connected to the hardware serial ports?

Yes, that works.  If you connect the Arduino TX pin 1 to the GPS RX, then everything you print to Serial goes to both the Serial Monitor window and the GPS device.
This works, because:

It's ok if you see the GPS configuration commands (if any) on the Serial Monitor window.  Your debug prints will appear after them.
The GPS device ignores anything that doesn't start with a '$' character; it ignores all your debug prints.

Just make sure the debug information never includes a $ at the start!

If you don't ever need to send anything to the GPS module then you don't need to connect the Arduino's TX pin to it.

@ Gerben .. Thanks.. @ Majenko .. will it do any harm if the pins are connected? My code is using only the commands to read from the gps. What are the possible data / commands that can be sent to the gps other than these?

@Vj1989, no harm to the pins (there are resistors on board to allow this).  As for other data and messages from the GPS, my NeoGPS library has a nice table here.  It's the smallest, fastest, most reliable and most accurate GPS library out there.  Commands that you can send to the GPS would be documented in the spec for your device.

While I agree with slash-dev, I feel unless you're really struggling with pin real state, you don't really need to have both the GPS serial and UART on the same pins (unless I'm missing some point or convention, in which case please do correct me).
When I was using a GPS module (GTOP013) with an Atmega328p, I just used the SoftwareSerial library to configure some unused pins (12 and 13 I think? it's been a while) as a dedicated RX/TX lines to the GPS, whilst the atmega's RX/TX remained reserved for a USB connection. Any time I needed anything sent to or from the GPS, I had a function to handle that. Also allowed me to keep polling the lines for data from the GPS to be printed onto the Serial.Console as desired for debugging.

@ Zaeche .. I'm using software serial pins for a GSM device and the program is not working when GPS is also connected to another set of Software serial pins. That's the reason why I'm using hardware serial ports for GPS.

Ah, I understand--thanks for clearing that up. I assume you'd prefer to Rx/Tx from the GSM and GPS simultaneously, as well as being able to debug using the hardware serial (thus, 1 hardware serial port + 2 software serial port).
As per this, serial ports can't be heard in tandem so I see why you had to reuse the hardware port for the GPS as well (the Mega has two hardware ports but honestly isn't as portable as the 328p).


text:
Arduino only sends HTTP 1.0 requests
I'm trying to connect to an http server that uses HTTP 1.1, my problem is that even thought the request is in HTTP 1.1 format and the server does actually use HTTP 1.1(I tried it in a browser) it only responds with HTTP 1.0. I'm using this modified example of the web client, I updated the Ethernet library yesterday and for my server I'm using Node 8.4.0, I'm testing with google first even though I know the server can respond with HTTP 1.1.
Ethernet shield model: Han Run HR911105A 16/02
Arduino: Mega 2560
 This sketch connects to a website (http://www.google.com)
 using an Arduino Wiznet Ethernet shield.

 Circuit:
 * Ethernet shield attached to pins 10, 11, 12, 13

 created 18 Dec 2009
 by David A. Mellis
 modified 9 Apr 2012
 by Tom Igoe, based on work by Adrian McEwen

 */

#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
//IPAddress server(74,125,232,128);  // numeric IP for Google (no DNS)
char server[] = "www.google.com";    // name address for Google (using DNS)

// Set the static IP address to use if the DHCP fails to assign
IPAddress ip(192, 168, 0, 177);

// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;

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

  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // try to congifure using IP address instead of DHCP:
    Ethernet.begin(mac, ip);
  }
  // give the Ethernet shield a second to initialize:
  delay(1000);
  Serial.println("connecting...");

  // if you get a connection, report back via serial:
  if (client.connect(server, 80)) {
    Serial.println("connected");
    // Make a HTTP request:
  client.print("GET / HTTP/1.1\r\n");
  client.print("Host: www.google.com\r\n");
  client.print("Content-Type: application/x-www-form-urlencoded\r\n");
  client.print("Cache-Control: no-cache\r\n");
  client.print("\r\n");
  } else {
    // if you didn't get a connection to the server:
    Serial.println("connection failed");
  }
}

void loop() {
  // if there are incoming bytes available
  // from the server, read them and print them:
  while (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
  }
}

With this I get the following response:

Thank you in advance

How does a 302 benefit from being HTTP 1.1?

It's just a test :P I don't really care about the result in this one, I just need an http 1.1 response so I can then connect the arduino to a socket.io server
I've tried many times with the 2 other servers and the only type of response I get is 1.0---OP

Did you try using a URL that returns a 200?

Han Run HR911105A 16/02 -- I do love the way people keep quoting the model number of the RJ45 socket as the board model...

Ignacio: I did try, the response is the following:
The reason for the bad request is because the handshake in the socket.io library needs an http 1.1 response, for this it sends 2 get requests. The library is washo4evr's library for socket.io.
http://i.imgur.com/qW2WVRH.png

The device sending the request has no bearing on if it is HTTP 1.0 or 1.1. Only the content has an effect.
That and what is in the path - and I suspect that may be your problem: your are going through a squid proxy - and an old version at that. It is most likely that the proxy is changing the request to be a 1.0 request instead of a 1.1 request.

Thank you: Turns out the local network where I was connected had an IP in this format:
xxx.xxx.70.xxx
And my IP was: xxx.xxx.80.xxx
Therefore the proxy was making the response go from 1.1 to 1.0


text:
Code is not looping correctly when running on battery
static const int dry = 570;
static const int wet = 225;
static const int RELAY = 2;
static const unsigned long DELAY_1_S      = 1000;
static const unsigned long DELAY_1_MINUTE = DELAY_1_S * 60;
static const unsigned long DELAY_1_HOUR   = DELAY_1_MINUTE * 60;
static boolean watering = false;

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

void loop() {
  int sensorVal = analogRead(A0);
  int percentageHumidity = map(sensorVal, wet, dry, 100, 0);
  Serial.print(percentageHumidity);
  Serial.println("%");
  if (!watering && percentageHumidity < 60){
    watering = true;
    Serial.println("Watering!!!");
    digitalWrite(RELAY, HIGH);
    delay(3*DELAY_1_S);
    digitalWrite(RELAY, LOW);
    watering = false;
  }
  Serial.println(DELAY_1_S * 10);
  delay(10*DELAY_1_S);
}

I have an analog reading at A0 from a capacitance water sensor. If the sensors read a value of 60% or less humidity it will activate a water pump. The water pump is connected through a 5v relay and the water pump has its independent power supply. For some reason, the code works when connected to the USB as intended, but when I power it with the battery it connects always the water pump.

Which board and which battery do you use? How are they connected?

Show your wiring.  If it works on USB but not on battery then it probably isn't the code that's the issue.  You got all the grounds connected?

Are your wet and dry values the same when running from battery? Have you determined if they should be changed?


text:
Why is their need of response time needed in esp8266 AT commands?
I am writing an AT commands firmware for esp8266 via connecting it to atmega2560.
Now the question is how will I come to know the response time for AT commands for writing its firmware to read the response?
in fact prior to this thought, the question comes why is their need of response time in AT commands?
does response time concept is there in all modules where AT commands are used like gsm modules, HC05,etc.

what is what you call 'response time'? there is no such thing. do you mean the time while the AT firmware sends the response after sending the command. that of course can't be instant. there is the communication over Serial and some processing time to handle the command in the firmware

If you're on about the prolific use of delay() after sending a command, is because back in the mists of time someone without a clue wrote a tutorial and did it wrong. People with even less of a clue copped it, and it grew from there. There is no call for any delay of you write your code properly with a send-expect model.

Okay thanks for your valuable suggestions45

Your esp8266 firmware isn't required to wait before responding to the atmega2560, but the reality is that it simply can't respond in zero-time. The esp will take some processing to interpret the command that was sent to it and to create the reply to the atmega. And that is even if it doesn't have to wait for some distant server.
If the esp has to send a WiFi request to a server (which has the same constraints of processing time, plus other requests ahead of yours), that only adds to the esp's delay in responding to the atmega.
The bottom line is that the esp isn't required to wait any amount of time to respond; its just however much time it takes to acquire any data it needs, plus processing time to format it and send it back to the atmega.


text:
Stepper motor not working as expected
Kunal Gupta:
Guys plss help me .... I am having issues in using stepper motor
I have tried both 28bjy with uln2003 and l293d .. giving it output supply of 5V .
Motor is vibrating but its shaft is not moving.
And even if shaft runs then it is different from what is expected by the logic of code
Similarly tried NEMA 17 stepper motor 4.5 KG using drv8825 driver and L293D driver ... Giving 12 v external supply.
And same results as 28bjy .... motor vibrating but its shaft is mot moving as expected or absolutely not moving
I have read and understood all the concept of driving stepper motor by full step method and hafl step method ....and using at first direct examples from net .. but still not figuring out what is the problem

Can you please show your code and your wiring? A vibrating stepper motor suggests, that the phases of the motor are not driven in the right order. I already wrote an answer to a question about the 28BYJ-48 stepper and the ULN2003 once. Maybe it helps you: https://arduino.stackexchange.com/questions/57089/stepper-motor-wont-reverse-turn-ccw/57095#57095

Try  lowering the rpm in the code. I had a similar issue with anything over about 18rpm using certain libraries with certain stepper motors.


text:
SPI between Master arduino and Slave arduino
How can I send the string from Slave SPI to Master SPI?
I want to write code in Bare Metal.
The problem which I am facing is I can't make out what will be my blocking function in Master SPI code when receiving data from slave SPI.
As my SPIF bit is cleared in MAster code as soon as I shift out SPDR register from master to receive byte which is coming from the slave.
#define spi_data_reg SPDR
//Naster read byte function
    uint8_t MA_SPI0_read_byte()
    {
        spi_port &= ~(1<<SS);
        spi_data_reg = 0;
        while(!(SPSR & (1<<SPIF)));                  //Wait until transmission complete
        return(spi_data_reg);                                 //Return received data
       spi_port |= (1<<SS);
    }

    //Slave send byte function
    void SL_SPI0_send_byte(uint8_t data)
    {
        spi_data_direc=(1<<MISO);   //MISO as OUTPUT
        spi_data_reg = data;
        while(!(SPSR &(1<<SPIF)));
    }

At first: spi_port |= (1<<SS); after the return wil not work. You'll never reach the line. Why do you initialize spi_data_reg = 0;? Have you set the master to input like spi_data_direc=(1<<MISO); elsewhere? I did not yet programmed SPI communications with the low level api, so I do not know if one of these could be the problem. But as no one else repsonded ... Just some ideas; better than nothing.


text:
legality of streaming data on 868 or 915 Mhz in EU/US
From what I read about duty cycles in the EU there is a 10% limitation (even less in some sub bands).
The modules I found have a max. rate of 300 kbps. Even if you max out the duty cycle that would only be 30kbps.
How do consumer devices like a digital walkie talkie operate here legally in the EU?
What am I missing?
Is there a frequency where I can legally stream constantly at more than 70kbps (not Wifi) ?

Anything in the 2.4GHz band. There's more than just WiFi that works at that frequency.

868MHz and 915MHz are ISM (Industrial, Scientific and Medical) bands which has both power and throughput limitation. It is designed for short burst of data, not for streaming as it is a shared resource. For walkie talkie, it operates on other unlicensed band like sharing the band with WiFi on 2.4GHz. If you need the bandwidth, use 2.4GHz.


text:
915Mhz vs Wifi (speed impact of duty cycle limitations)
I am currently using an esp32 with Wifi. I need at least 15kByte/s constant throughout. This works fine but I am not happy with the range.
I came across the RFM69HCW 915MHz module. It is stated with 300 kbps.
Now what is confusing me are duty cycle regulations. Various countries have a 1% limit.
Is this limit considered in the 300 kbps? Or do I effectively only get 3 kbps because I cannot constantly send?

300kbps is the data transmission rate. Not the throughput rate.
That means that yes, if you only transmit for 1% of the time then for 1% of the time you are getting 300kbps - i.e., 3kbps as you correctly surmised.


text:
Using Flexinol Or Muscle Wire To Control Paper Flower Petal With Arduino
I am relatively new to Arduino and I am looking to use flexinol or muscle wire to control flower petals. I think I will need to control 4 sets of the wire. I have totally no idea of how to wire the components together, if I will need to get additional parts like a transistor or battery, and what type/thickness of wire I should get.

this question is not Arduino specific ... you would have the same question if you were using a Raspbery Pi or any other microcontroller

And you haven't given any information about your actual hardware. Please provide a link to the product, that you want to use (somewhere, where you can look at the datasheet of the product)

If you aren't willing to do some brain work to figure out the problem, why should we help you?


text:
I want to make two arduino to communicate over different wifi. Is that possible?
I want to make any 2 Arduino module from different places to communicate over wifi. I really need to know if it possible? If yes, advice me more about it. I want send data from sensor module from one Arduino to another and vice versa. That's the basic idea. Do I need a third party services such as cloud services to make it happen? Or simply can send ovee wifi with the help of Ip adress. Sorry, I have less knowledge on this. Help me out. Thank you in advance.

If they are on the same (wifi) network; then yes.
If you are on a different network, it would be more difficult. You would have to setup port forwarding on your router. Then you would have to somehow know the public IP address of the other router. These addresses can change from time to time with certain ISPs. I wouldn't advice doing this.
Instead I'd go with an third party service. For example Adafruits offers an MQTT server. I'd probably use this even if they are on the same network.


text:
WS2812B Reset time
i am trying to implement the ws2812b with an atmega8,but i didn't understand a thing very well. if i pull low for >50 us, it says it resets, but what does that mean? it resets the current LED all data to 0 and latches the next data to the next led?

welcome, it helps if you add a reference to 'it' in 'it says', probably a datasheet of the WS2812B you are using (and add the page/fragment or copy it).

It's the "communication" reset.  You pull the data pin low for 50uS or more to start a new batch of communication.
It's illustrated in the datasheet here:

As you can see, between each batch of bits being sent the reset code is set. This is so that the first chip knows to start receiving again and not pass any data on until it's had all 24 of its bits.

so, the reset code needs to be sent between each 24 bits, right?

No. Between each 24 * NUM_LEDS bits.

aaah, got it, so it's for when the all the data is sent, so i can send new data again. thanks!

@SoxxZ_ Btw, it is sometimes used to stretch comunication. The data for single led are sent and then MCU can do something else for short time (as far as it's not longer than reset pulse).


text:
Using Arduino to create a countdown that unlock a box
Am new to Arduino. So permit me if I sound so novice.
I want to create a countdown device (a clock that will countdown or something) that will unlock a box when the time is up.
As an example, let say, I set the clock to start counting down from 2hours, but when it remains 5mins for the countdown to elapse, the box will unlock
What are the things needed for it to work as all examples I see are mostly for opening the door or box when the temperature changes.

see the BlinkWithoutDelay example.

Some kind of display to show the remaining time. Either an LCD display, or a 4-digit 7-segment display. For the latter, there there are breakout boards that already have the needed circuitry to driver them. For the latch, you could use a servo. Or alternatively a solenoid.

This sounds as an escape room puzzle.
From an electronic point of view you need something to lock/unlock the box like a servo motor, a stepper motor or (best option) a normally closed solenoid. You might need some components to drive such locking mechanism, like a mosfet or transistor (possibly a darlington), depending on which device you choose and what voltage it requires to operate. Simplest solution is a servo motor which doesn’t require anything, but has a low torque, meaning the box can easily be forced. Most robust and reliable solution is a NC solenoid, common ones are 12V so you’ll need a p-channel enhance mosfet and a couple of resistors to drive it from an Arduino.
To display the time you’ll probably want to go for an LCD, common ones are 16 col x 2 rows, most have an integrated chip to drive them using only a few wires.
Apart from that, you need a battery pack (voltage and power depending on your locking circuit choice) and may be a push button (for safety unlock).
From a software perspective you want to create a loop which starts by locking the box and then counts down the time: when the time left is less than 5 mins it activates the unlocking mechanism circuit.
int current = 0;
const int max = 2 * 60 * 60; // 2hrs in sec
const int grant = 5 * 60; // 5mins in sec
bool unlocked = false;

void setup() {
    lock();
}

// executed once every second
void loop() {
    // any safety open check should be performed here...
    // if still locked and less than 5 mins to end
    if (!unlocked && current > max - grant) {
        unlock();
    }

    display(current++);
    wait(1000);
}

// does what it is needed to unlock and sets the unlocked variable to true
void unlock() { ... }

// does what it is needed to lock and sets the unlocked variable to false
void lock() { ... }

void display(int secs) {
    int h = secs / (60 * 60);
    int m = (secs / 60) % 60;
    int s = secs % 60;
    // display on LCD the values above with the proper formatting
}

A couple of notes:

if you go for a normally closed solenoid be sure to have a way to get inside the box if something goes wrong with your circuit or if the batteries get drained
you might want to have a hidden button or other way to force the unlock, especially for debugging and testing

You should probably have current = (millis() - startMillis) / 1000; in loop(), and no current++.

I tried to make it simpler to understand, but you are right: I’m not taking into consideration any time spent while looping. Also consider that the loss will almost always be in the order of 10-20ms... but you are definitely right: my “clock” implementation will drift for sure


text:
Help needed!!! I have an upcoming exam
I have an upcoming exam about the codes and stuff. Its about the basics like "blink with delay" and the "millis function". I need to get these things learned but i have no idea how?! Does anybody know a good site or how i can learn this?

Why don't you use the material your teacher provided you with? Or aren't there any sources? The ardiuno.cc site teaches you some basics https://www.arduino.cc/en/Tutorial/HomePage . But that's lot of stuff, so i would prefer the material from school. If you have an Arduino to use it, you can install the Arduino IDE and try some of the examples and learn from it.

Don't you mean "blink without delay"? The point is that the delay() function is to be avoided.

You should get an Arduino, a couple of LEDs, properly sized current limiting resistors, and spend a couple of days figuring out how to write a sketch that blinks the 2 LEDs at the same time on different intervals (Say you blink the first LED on and off every 3 seconds and the 2nd LED every 2 seconds.) If you figure that out, you will understand using millis() to manage timed events well enough for an exam.

There are tons of tutorials on the web about this (if you search for terms like "arduino blink without delay" or "arduino millis"). Even on this site the principle has been described numerous times. You should read some tutorials about it. If you don't have the actual Arduino hardware, you can use a simulator like from tinkercad. Try, what you have read in the tutorials and you will be able to figure this out fast.

Learning to write code really takes practice - you learn far more by doing it than by reading about it. Start with the basic Blink example - search for a tutorial online if you want one, there are many - and get that running. Then play with it. Change the blink interval. Try adding a second LED, perhaps it turns off when the other turns on, for instance.
Every time you touch the code you'll have an "opportunity" to make a mistake or a typo. Fixing those will give you some insights you'll never get from reading about coding.
Once you've "squeezed all the juice" out of Blink, move on to Blink Without Delay. Run it, just as it is, at first. Than start tweaking it. Change one or both of the blinking periods. Again, try adding another LED with yet another blink rate.
These hands-on games are the best way to learn this stuff. Having someone (or Arduino Stack Exchange) who can help you when you're stuck is a great resource but the things you discover and the skills you acquire on your own when you fix your own mistakes are the ones that will stick with you (even 50 years later! ;-)


text:
Sim800L not working
I have been trying to set up the SIM800L. The LED is not blinking...
I am using the LM2596 to convert from 5V to 4.3V (I did try with 3.7 <= Vout <=4.3 V) to power the module. With a 5V/2A power supply nothing works aswell.

Any ideas? Thanks in advance!

Have you tried connecting it to an Arduino at any point?

is the LED supposed to blink?

Yes, I did connect to test AT commands. The LED should blink since I am powering the module.

have you checked the power supply voltage at the SIM800L module power pins?

the soldering job on the module pins looks questionable .... please provide a clear closeup of the module

I did check for continuity with a multimeter and the solder joints although not great, they conduct. I have at the module 4.2/4.3 V.

According to this site if you give more than 2.8V on the SIM800L you will kill the module.


text:
Unable to access SD Card when using GPS and MS5611 sensors
I'm trying to connect multiple sensors to an arduino and write the retrieved data in to a SD. When I test each module separately it works properly, but when I put everything together the SD card module doesn't work, can anybody help me?
This is the code that I'm using:
#include <Arduino.h>
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <MS5611.h>

// SD
#define GPS_STORED_DATA_FILE_NAME "gps.txt"
#define SDCARD_PIN 10
bool _sdError = false;

// GPS
#define GPS_RX_PIN 9
#define GPS_TX_PIN 8
#define GPS_BAUD 9600
TinyGPSPlus _gps;
SoftwareSerial _ss (GPS_RX_PIN, GPS_TX_PIN);
unsigned long _timeLastMeasurementGps;

// MS5611
MS5611 _ms5611;

void sdTest(double latitude, double longitude, float elevation, double time) {
  if (_sdError) {
    //Serial.print("SD ERROR. Stopping writing");
    return;
  }
  String fileName = GPS_STORED_DATA_FILE_NAME;
  File myFile = SD.open(fileName, FILE_WRITE);

  if (myFile) {
    Serial.print("Writing to ");
    Serial.print(fileName);
    Serial.print("...");
    //myFile.println("testing 1, 2, 3.");
    myFile.print(latitude);
    myFile.print(" | ");
    myFile.print(longitude);
    myFile.print(" | ");
    myFile.print(elevation);
    myFile.print(" | ");
    myFile.println(time);
    myFile.flush();
    // close the file:
    myFile.close();
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening");
    Serial.print(fileName);
    _sdError = true;
  }

  // re-open the file for reading:
  myFile = SD.open(fileName);
  if (myFile) {
    Serial.print(fileName);
    Serial.println(":");

    // read from the file until there's nothing else in it:
    while (myFile.available()) {
        // Serial.write(myFile.read());
      myFile.read();
    }
    // close the file:
    myFile.close();
  } else {
    // if the file didn't open, print an error:
    Serial.print("error opening ");
    Serial.println(fileName);
  }
}

void smartDelay(unsigned long ms)
{
  unsigned long start = millis();
  do
  {
    while (_ss.available())
      _gps.encode(_ss.read());
  } while (millis() - start < ms);
}

void setupSd() {
  Serial.print("Initializing SD...");
  pinMode(SS, OUTPUT);

  if (!SD.begin(SDCARD_PIN))
    Serial.println(" ERROR");
  else
    Serial.println(" DONE");
}

void setupGps() {
  Serial.print("Initializing GPS...");
  _ss.begin(GPS_BAUD);
  smartDelay(1000);
  _timeLastMeasurementGps = millis();
  Serial.println(" DONE");
}

void setupMs5611()
{
   Serial.print("Initializing vario...");
   while(!_ms5611.begin(MS5611_ULTRA_HIGH_RES))
  {
    Serial.println("Could not find a valid MS5611 sensor, check wiring!");
    delay(500);
  }
  // Serial.print("ms5611 Oversampling: ");
  // Serial.println(_ms5611.getOversampling());
  Serial.println(" DONE");
}

void setup()
{
  Serial.begin(115200);
  setupMs5611();
  setupSd();
  setupGps();
}

void loop()
{
  delay (100);
   sdTest(1, 2, 3, 4);
}

Thanks in advance!

I suspect that your problem lies with how your SD card is connecting via the SPI bus.
The problem is that a lot of Serial Peripheral Interface (SPI) devices, particularly the cheaper ones, don't properly put the MISO pin into high-impedance when SS is pulled high.
I had almost exactly this situation with one of my projects. I eventually resolved it by placing a tri-state buffer in the MISO line for each of the SPI devices.
I used a 74HC125 (4-channel tri-state buffer).
This is the page on Better SPI Bus Design in 3 steps that finally got me on the right track. I think the explanations are reasonably clear (at least compared with many other sites I found!).

If you are using an SPI SD breakout board (like 50 cents on AliExpress), than it does work only when not connected to other SPI devices.
However, when connected to other SPI devices it cannot communicate. The only way I could overcome this problem was to use an SD recorder/logger, which is a shield that fits on an Arduino (and contains a small proto space and sometimes a RTC. Or use a device that has multiple SPI ports.
Type (SD reader) that do not work together with other SPI devices:

Type (SD Data recorder/logger) that do work together with other SPI devices:

I just tried to connect the GPS to 5V and the SD worked, but when I plugged the LCD screen that uses 3.3V then it stopped working again. Could you recommend an SD module to buy it?

Updated my answer ...

The SD I have is the following:
https://www.banggood.com/Micro-SD-TF-Card-Memory-Shield-Module-SPI-Mciro-SD-Adapter-For-Arduino-p-919914.html
Using the SdFat library I managed to make it work a "little": if I draw something in the external screen (PCD8544) during the setUp process the SD card will not work, otherwise it will work. I'll end up buying a new SD card reader.


text:
How to identify Adafruit Feather 32u4 via mac id/UUID/etc
I'm working with a couple Feather 32u4 devices and I've had success so far in setting them up as transmitters and receivers as well as hooking up one of them to a Featherwing Ethernet and talking over MQTT. My problem is that I'm trying to find out how I can implement some sort of identification system among them so that I can send packets to a specific radio. The approach I'd like to avoid is that of writing different versions of the code with different IDs hardcoded in each and uploading them to a radio (so ideally I'm wondering if there's a way to access an inherent mac ID/UUID of each radio). Each radio did come with what appears to be a mac ID printed on a piece of paper but I don't know how to access that directly from the device.
Thanks!

It doesn't sound like any of the components in your system have hardware unique ID's.  The ATmega does not, and if your radio does is unknowable without it being specifically identified, but most likely not given the included piece of paper.

There are multiple boards partially named "Feather 32U4". You need to edit your question to specify which one and post a link that provides more information on it.

I'm quite sure the reason they print a mac address on a sticker and put it in the package is that they have no way of storing the address in the the feather wing, or at least don't bother to do so if there is a place to store it.
It's up to you to get that address to your Ethernet.begin() call.
FYI, I have been trying to use EEPROM to store the mac address, but the bootloader appears to blow away EEPROM with every reboot.  If I figure that one out I'll update.


text:
analogWrite mosfet problem
i have a custom atmega328p board which have connected to pin 9 the gate of a MOSFET.
If i run a simple sketch like:
void setup() {

}
void loop() {
  analogWrite(9,70);
}

The motor connected to the mosfet works just fine, from 70pwm to 255pwm.
On the other sketch i'm receiving serial data from an android app via bluetooth. Ive 2 Servo motors and a DC motor connected to the mosfet.
The 2 servos works like expected, the DC motor doesn't spin unless i use a 255pwm.
void loop() {
  if(Serial.available() > 0){
      state = Serial.read();
  }
  if (state == 'S') {
      servoONE.write(90);
      servoTWO.write(90);
      analogWrite(MOSFET,MOSFET_LOW);
  }
  else if (state == 'F') {
      analogWrite(9,70);
      servoONE.write(90);
      servoTWO.write(90);
  }
  else if (state == 'L') {
      servoONE.write(MAX_SERVO);
      servoTWO.write(MIN_SERVO);
  }
  else if (state == 'R') {
      servoONE.write(MIN_SERVO);
      servoTWO.write(MAX_SERVO);
  }
  else if (state == 'Q') {
      analogWrite(MOSFET,MOSFET_HIGH);
      servoONE.write(MAX_SERVO);
      servoTWO.write(MIN_SERVO);
  }
  else if (state == 'E') {
      analogWrite(MOSFET,MOSFET_HIGH);
      servoONE.write(MIN_SERVO);
      servoTWO.write(MAX_SERVO);
  }
}

Do you know why the same motor works on the first sketch with any pwm above 70 and on the second sketch it only works at 255?

You have a timer conflict.
Pin 9 is OC1A which is the Output Compare Channel A pin of Timer 1. However the Servo.h library also uses timer 1.
So you can't use servos and still use pins 9 (OC1A) and 10 (OC1B) as PWM.
However, you can still use pins 3, 5, 6 and 11 as PWM since they are on other timers.

Ok, thanks for the quick answer, i see the pin 11 is the MOSI pin and im using an ISP programmer to program my board. Will i be able to program my board if i use pin 11 as PWM ?

Of course. So long as what you have connected to it doesn't interfere with the ICSP signal - and the gate of a MOSFET shouldn't.

Tested right now using pin 3 instead of pin 9, it works!!!  You saved me a lot of troubles :D


text:
Countdown sometime stop
I've made a game with 3 countdowns and 1 global countdown.

When we start, the global one, go from 45:00 to 00:00.
The 1 go from 15:00 to 00:00 and if it reach 00:00:
The 2 start and go from 15:00 to 00:00 and it if reach 00:00:
The 3 start and go from 15:00 to 00:00

If you win little game, you can stop a countdown and start the next. If you win the 3 games, you stop the 3 countdown and the global too.
But sometime, my 2nd countdown stop itself, sometime at 13:58 or 10:54…
Is it possible that the millis() cause that bug ? Do you have an idea to improve my code and fix that ?
Fun fact : Sometime countdowns go from 01 to 60 instead of 00 to 59……
Sorry for my english, i'm not native speaker.
//14-06-17 Correctifs LED
//10-06-17 Correctif Jeu 1

#include "musical_notes.h"
#include "TM1637.h"
#include "SevenSegmentTM1637.h"
#include "OnewireKeypad.h"
#include "Password.h"

SevenSegmentTM1637    displaya(4, 5);
SevenSegmentTM1637    displayb(6, 7);
SevenSegmentTM1637    displayc(8, 9);
SevenSegmentTM1637    displayd(50, 51);

TM1637 tm1637a(50, 51); //TIMER GLOBAL 45
TM1637 tm1637b(4, 5); //TIMER 1 15
TM1637 tm1637c(6, 7); //TIMER 2 15
TM1637 tm1637d(8, 9); //TIMER 3 15

char KEYS[] = {
  '1', '4', '7', '*',
  '2', '5', '8', '0',
  '3', '6', '9', '#',
  'A', 'B', 'C', 'D'
};
OnewireKeypad <Print, 16 > KP(Serial, KEYS, 4, 4, A0, 4700, 1000, ExtremePrec );
Password password = Password( "8751" );

//PREMIER JEU
int checkbranche = 23;
int checkbrancheb = 22;
int checkbranchec = 24;
int state = HIGH;
int reading;
int readingb;
int readingc;
int previous = LOW;
int previousb = LOW;

int readingstart;
int checkstart = A1;

int speakerPin = 52;
int runOPEN = 0;
int runJEU1 = 0;
int runJEU2 = 0;
int runJEU3 = 0;
int runFAILGLOBAL = 0;

int winJEU1 = 0;
int winJEU2 = 0;
int winJEU3 = 0;
int winGLOBAL = 0;
int looseGLOBAL = 0;

int LED_jeu1_V = 30;
int LED_jeu1_R = 31;
int LED_jeu2_V = 33;
int LED_jeu2_R = 32;
int LED_jeu3_V = 35;
int LED_jeu3_R = 34;

int LED_jglobal1 = 36;
int LED_jglobal2 = 37;
int LED_jglobal3 = 38;
int LED_jglobal4 = 39;

int runcode = 0;

int second=0, minute=45, hour=0; // déclarer des variables de temps
int second1=0, minute1=15, hour1=0; // déclarer des variables de temps
int second2=0, minute2=15, hour2=0; // déclarer des variables de temps
int second3=0, minute3=15, hour3=0; // déclarer des variables de temps
long previousTime = 0;//détient temps précédent en ms
long previousTime1 = 0;//détient temps précédent en ms
long previousTime2 = 0;//détient temps précédent en ms
long previousTime3 = 0;//détient temps précédent en ms
long previousDelay = 0;//détient temps précédent en ms depuis buzzer était actif
long previousDelay1 = 0;//détient temps précédent en ms depuis buzzer était actif
long previousDelay2 = 0;//détient temps précédent en ms depuis buzzer était actif
long previousDelay3 = 0;//détient temps précédent en ms depuis buzzer était actif
long interval = 60000;//60 secondes de retard
long interval1 = 60000;//60 secondes de retard
long interval2 = 60000;//60 secondes de retard
long interval3 = 60000;//60 secondes de retard

int dismentel1 = 0; int fail1 = 0;
int dismentel2 = 0; int fail2 = 0;
int dismentel3 = 0; int fail3 = 0;
int dismentel4 = 0; int fail4 = 0;

char hour_str[4]; // Pour Convertir int en char
char minute_str[4]; // Pour Convertir int en char
char second_str[4]; // Pour Convertir int en char
char timeInt_str[0];  // Pour Convertir int en char

int accessgame = 3; //Activation de led quand les minutes arrivent à 3

unsigned char halfsecond=0;

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

  KP.SetHoldTime(3000);
  KP.SetKeypadVoltage(5.0);
  KP.ShowRange();

   displaya.begin();
   displayb.begin();
   displayc.begin();
   displayd.begin();

   tm1637a.set(4);
   tm1637a.init();
   tm1637a.point(POINT_ON);

   tm1637b.set(4);
   tm1637b.init();
   tm1637b.point(POINT_ON);

   tm1637c.set(4);
   tm1637c.init();
   tm1637c.point(POINT_ON);

   tm1637d.set(4);
   tm1637d.init();
   tm1637d.point(POINT_ON);

   pinMode(checkbranche, INPUT);
   pinMode(checkbrancheb, INPUT);
   pinMode(checkbranchec, INPUT);
   pinMode(checkstart, INPUT);
   pinMode(speakerPin, OUTPUT);

   pinMode(LED_jeu1_V, OUTPUT);
   pinMode(LED_jeu1_R, OUTPUT);
   pinMode(LED_jeu2_V, OUTPUT);
   pinMode(LED_jeu2_R, OUTPUT);
   pinMode(LED_jeu3_V, OUTPUT);
   pinMode(LED_jeu3_R, OUTPUT);

   pinMode(LED_jglobal1, OUTPUT);
   pinMode(LED_jglobal2, OUTPUT);
   pinMode(LED_jglobal3, OUTPUT);
   pinMode(LED_jglobal4, OUTPUT);

   delay(1000);

};

// run loop (forever)
void loop() {

readingstart = digitalRead(checkstart);
reading = digitalRead(checkbranche);
readingb = digitalRead(checkbrancheb);
readingc = digitalRead(checkbranchec);

if (runcode < 1) {
Serial.println("WHAT");

      if (readingstart == HIGH) {

        for (; runOPEN < 1; runOPEN++) {
          uhoh();
         }

    countdown();

Serial.print(halfsecond);
Serial.println(" ");

  if (dismentel1 == 1) {digitalWrite(LED_jglobal1, HIGH);} else {digitalWrite(LED_jglobal1, LOW);}
  if (dismentel2 == 1) {digitalWrite(LED_jglobal2, HIGH);} else {digitalWrite(LED_jglobal2, LOW);}
  if (dismentel3 == 1) {digitalWrite(LED_jglobal3, HIGH);} else {digitalWrite(LED_jglobal3, LOW);}
  if (dismentel4 == 1) {digitalWrite(LED_jglobal4, HIGH);} else {digitalWrite(LED_jglobal4, LOW);}

// GESTION DU JEU 1 //
  if (reading == LOW) {  //REVISION 1 HIGH -> LOW
      countdown1();

      if (second1 > 0 && minute1 >= 0) {
          int8_t timeDisp1[4];
          timeDisp1[0] = minute1 / 10;
          timeDisp1[1] = minute1 % 10;
          timeDisp1[2] = second1 / 10;
          timeDisp1[3] = second1 % 10;
          tm1637b.display(timeDisp1);

      if (minute1 < accessgame) {
        digitalWrite(LED_jeu1_V, LOW);
        digitalWrite(LED_jeu1_R, HIGH);
      } else {
        digitalWrite(LED_jeu1_V, HIGH);
        digitalWrite(LED_jeu1_R, LOW);
      }

          dismentel1 = 0;

      } else {
          displaya.print("FAIL");
            digitalWrite(LED_jeu1_V, HIGH);
            digitalWrite(LED_jeu1_R, LOW);
            for (; runJEU1 < 1; runJEU1++) {
              squeak();
            }
           fail1 = 1;
      }

  } else {
      displaya.print("--5-");
      digitalWrite(LED_jeu1_V, LOW);
      digitalWrite(LED_jeu1_R, HIGH);
      for (; winJEU1 < 1; winJEU1++) {
        wingame();
       }
       dismentel1 = 1;
  }

// GESTION DU JEU 1 //

// GESTION DU JEU 2 //
  if (readingb == HIGH) {
    dismentel2 = 1;
  }

  if ((dismentel1 == 1 or fail1 == 1) && dismentel2 == 0) {
    countdown2();

    if (second2 > 0 && minute2 >= 0) {
      int8_t timeDisp2[4];
      timeDisp2[0] = minute2 / 10;
      timeDisp2[1] = minute2 % 10;
      timeDisp2[2] = second2 / 10;
      timeDisp2[3] = second2 % 10;
      tm1637c.display(timeDisp2);
      if (minute2 < accessgame) {
        digitalWrite(LED_jeu2_V, LOW);
        digitalWrite(LED_jeu2_R, HIGH);
      } else {
        digitalWrite(LED_jeu2_V, HIGH);
        digitalWrite(LED_jeu2_R, LOW);
      }
      dismentel2 = 0;
    } else {
        displayb.print("FAIL");
          digitalWrite(LED_jeu2_V, HIGH);
          digitalWrite(LED_jeu2_R, LOW);
          for (; runJEU2 < 1; runJEU2++) {
            squeak();
          }
         fail2 = 1;
    }

  } else if ((dismentel1 == 1 or fail1 == 1)  && dismentel2 == 1){
      displayb.print("-7--");
      digitalWrite(LED_jeu2_V, LOW);
      digitalWrite(LED_jeu2_R, HIGH);
      for (; winJEU2 < 1; winJEU2++) {
        wingame();
       }
       dismentel2 = 1;
  } else {
    displayb.print("----");
      digitalWrite(LED_jeu2_V, HIGH);
      digitalWrite(LED_jeu2_R, HIGH);
      }

// GESTION DU JEU 2 //

// GESTION DU JEU 3 //

  if (readingc == HIGH) {
    dismentel3 = 1;
  }

  if ((dismentel2 == 1 or fail2 == 1) && dismentel3 == 0) {
    countdown3();

    if (second3 > 0 && minute3 >= 0) {
      int8_t timeDisp3[4];
      timeDisp3[0] = minute3 / 10;
      timeDisp3[1] = minute3 % 10;
      timeDisp3[2] = second3 / 10;
      timeDisp3[3] = second3 % 10;
      tm1637d.display(timeDisp3);
      if (minute3 < accessgame) {
        digitalWrite(LED_jeu3_V, LOW);
        digitalWrite(LED_jeu3_R, HIGH);
      } else {
        digitalWrite(LED_jeu3_V, HIGH);
        digitalWrite(LED_jeu3_R, LOW);
      }
      dismentel3 = 0;
    } else {
        displayc.print("FAIL");
          digitalWrite(LED_jeu3_V, HIGH);
          digitalWrite(LED_jeu3_R, LOW);
          for (; runJEU3 < 1; runJEU3++) {
            squeak();
          }
         fail3 = 1;
    }

  } else if ((dismentel2 == 1 or fail2 == 1)  && dismentel3 == 1){
      displayc.print("---1");
      digitalWrite(LED_jeu3_V, LOW);
      digitalWrite(LED_jeu3_R, HIGH);
      for (; winJEU3 < 1; winJEU3++) {
        wingame();
       }
       dismentel3 = 1;
  } else {
    displayc.print("----");
      digitalWrite(LED_jeu3_V, HIGH);
      digitalWrite(LED_jeu3_R, HIGH);
      }

      } else {

second=0; minute=45; hour=0; // déclarer des variables de temps
second1=0; minute1=15; hour1=0; // déclarer des variables de temps
second2=0; minute2=15; hour2=0; // déclarer des variables de temps
second3=0; minute3=15; hour3=0; // déclarer des variables de temps
previousTime = 0;//détient temps précédent en ms
previousTime1 = 0;//détient temps précédent en ms
previousTime2 = 0;//détient temps précédent en ms
previousTime3 = 0;//détient temps précédent en ms
previousDelay = 0;//détient temps précédent en ms depuis buzzer était actif
previousDelay1 = 0;//détient temps précédent en ms depuis buzzer était actif
previousDelay2 = 0;//détient temps précédent en ms depuis buzzer était actif
previousDelay3 = 0;//détient temps précédent en ms depuis buzzer était actif
interval = 60000;//60 secondes de retard
interval1 = 60000;//60 secondes de retard
interval2 = 60000;//60 secondes de retard
interval3 = 60000;//60 secondes de retard
runOPEN = 0;
dismentel1 = 0; fail1 = 0;
dismentel2 = 0; fail2 = 0;
dismentel3 = 0; fail3 = 0;
dismentel4 = 0; fail4 = 0;
    displaya.print("-   ");
    displayd.print("-   ");

      }

}

// GESTION DU JEU 3 //

// VALIDATION GLOBALE PAR DIGICODE //
  char Key;
  byte KState = KP.Key_State();

  if (KState == PRESSED) {
    if ( Key = KP.Getkey() ) {
      Serial << "Pressed: " << Key << "\n";
      switch (Key) {
        case '*': checkPassword(); break;
        case '#': password.reset(); break;
        default: password.append(Key);
      }
    }
  }
  else if (KState == HELD) {
    Serial << "Key:" << KP.Getkey() << " being held\n";
  }
// VALIDATION GLOBALE PAR DIGICODE //

};

void beep (int speakerPin, float noteFrequency, long noteDuration)
{
  int x;
  // Convert the frequency to microseconds
  float microsecondsPerWave = 1000000/noteFrequency;
  // Calculate how many HIGH/LOW cycles there are per millisecond
  float millisecondsPerCycle = 1000/(microsecondsPerWave * 2);
  // Multiply noteDuration * number or cycles per millisecond
  float loopTime = noteDuration * millisecondsPerCycle;
  // Play the note for the calculated loopTime.
  for (x=0;x<loopTime;x++)
          {
              digitalWrite(speakerPin,HIGH);
              delayMicroseconds(microsecondsPerWave);
              digitalWrite(speakerPin,LOW);
              delayMicroseconds(microsecondsPerWave);
          }
}

void waka() {
  for (int i=1000; i<3000; i=i*1.05) {
    beep(speakerPin,i,10);
  }
  delay(100);
  for (int i=2000; i>1000; i=i*.95) {
    beep(speakerPin,i,10);
  }
    for (int i=1000; i<3000; i=i*1.05) {
    beep(speakerPin,i,10);
  }
  delay(100);
  for (int i=2000; i>1000; i=i*.95) {
    beep(speakerPin,i,10);
  }
    for (int i=1000; i<3000; i=i*1.05) {
    beep(speakerPin,i,10);
  }
  delay(100);
  for (int i=2000; i>1000; i=i*.95) {
    beep(speakerPin,i,10);
  }
    for (int i=1000; i<3000; i=i*1.05) {
    beep(speakerPin,i,10);
  }
  delay(100);

            beep(speakerPin, note_Bb5,300); //B b
          delay(50);
          beep(speakerPin, note_C6,300); //C
          delay(50);
          beep(speakerPin, note_Ab5,300); //A b
          delay(50);
          beep(speakerPin, note_Ab4,300); //A b
          delay(50);
          beep(speakerPin, note_Eb5,500); //E b
          delay(500);
}

void squeak() {
//  for (int i=100; i<5000; i=i*1.45) {
//    beep(speakerPin,i,60);
//  }
//  delay(10);
  for (int i=3500; i>10; i=i/1.15) {
    beep(speakerPin,i,60);
  }
}
void wingame() {
  for (int i=100; i<5000; i=i*1.45) {
    beep(speakerPin,i,60);
  }

}

void uhoh() {
  for (int i=1000; i<2000; i=i*1.10) {
    beep(speakerPin,i,10);
  }
  delay(50);
  for (int i=1000; i>500; i=i*.90) {
    beep(speakerPin,i,10);
  }
  delay(50);
  for (int i=1000; i<2000; i=i*1.10) {
    beep(speakerPin,i,10);
  }
  delay(50);
  for (int i=1000; i>500; i=i*.90) {
    beep(speakerPin,i,10);
  }
  delay(50);
    for (int i=1000; i<2000; i=i*1.10) {
    beep(speakerPin,i,10);
  }
  delay(50);
  for (int i=1000; i>500; i=i*.90) {
    beep(speakerPin,i,10);
  }
  delay(50);
    for (int i=1000; i<2000; i=i*1.10) {
    beep(speakerPin,i,10);
  }
  delay(50);
  for (int i=1000; i>500; i=i*.90) {
    beep(speakerPin,i,10);
  }
  delay(50);
    for (int i=1000; i<5000; i=i*1.05) {
    beep(speakerPin,i,10);
  }
 delay(300);

  for (int i=1000; i<3000; i=i*1.03) {
    beep(speakerPin,i,10);
  }
  for (int i=3000; i>1000; i=i*.97) {
    beep(speakerPin,i,10);
  }
}

void checkPassword()
{
  if (password.evaluate()) {
    Serial.println("Success");
    runcode = 1;
    displayd.print(" YOU");
    displayd.print(" YOU");
    displaya.print(" ARE");
    displaya.print(" ARE");
    displayb.print(" THE");
    displayb.print(" THE");
    displayc.print("BEST");
    displayc.print("BEST");
    digitalWrite(LED_jglobal4, HIGH);

    for (; winGLOBAL < 1; winGLOBAL++) {
      waka();
     }
    password.reset();
  } else {
    Serial.println("Wrong");
    password.reset();

    for (; looseGLOBAL < 1; looseGLOBAL++) {
    squeak();
    looseGLOBAL = 0;
    }

  }
}
/**********************************************************************
 *                        GLOBAL                                      *
 **********************************************************************/
void countdown(){

 static unsigned long lastTick = 0; // mettre en place une variable locale pour maintenir la dernière fois que nous décrémentés une seconde
  static unsigned long currentMillis = 0;
  // (variables statiques sont initialisées une fois et conservent leurs valeurs entre les appels de fonction)
  // diminuer à une seconde tous 1000 millisecondes
  if (second > 0) {
    if (millis() - lastTick >= 1000) {
      lastTick = millis();
      second--;

      int8_t timeDisp[4];
      timeDisp[0] = minute / 10;
      timeDisp[1] = minute % 10;
      timeDisp[2] = second / 10;
      timeDisp[3] = second % 10;
      tm1637a.display(timeDisp);
      tm1637a.point(POINT_ON);

    }
  } else {
       displayd.print("FAIL");
      for (; runFAILGLOBAL < 1; runFAILGLOBAL++) {
          squeak();
      }
  }
 // décrémenter une minute toutes les 60 secondes
  if (minute > 0) {
    if (second <= 0) {
      minute--;
      second = 60; // remettre les secondes à 60
    }
  }
  // décrémenter une heure tous les 60 minutes
  if (hour > 0) {
    if (minute <= 0) {
      hour--;
      minute = 60; // réinitialiser minutes à 60
    }//closes if
  }//closes if

  //le code ci-dessous bips de la sirène une fois par minute.
  currentMillis = millis();
  if (currentMillis - previousTime > interval)
  {
    previousTime = currentMillis;
    previousDelay = currentMillis;
  }

  if (currentMillis - previousDelay > 100) {//100ms durée de chirp
  }
} //close countdown();

/**********************************************************************
 *                        JEU1                                        *
 **********************************************************************/
void countdown1(){

 static unsigned long lastTick1 = 0; // mettre en place une variable locale pour maintenir la dernière fois que nous décrémentés une seconde
  static unsigned long currentMillis1 = 0;
  // (variables statiques sont initialisées une fois et conservent leurs valeurs entre les appels de fonction)
  // diminuer à une seconde tous 1000 millisecondes
  if (second1 > 0) {
    if (millis() - lastTick1 >= 1000) {
      lastTick1 = millis();
      second1--;

    }
  }
 // décrémenter une minute toutes les 60 secondes
  if (minute1 > 0) {
    if (second1 <= 0) {
      minute1--;
      second1 = 60; // remettre les secondes à 60
    }
  }
  // décrémenter une heure tous les 60 minutes
  if (hour1 > 0) {
    if (minute1 <= 0) {
      hour1--;
      minute1 = 60; // réinitialiser minutes à 60
    }//closes if
  }//closes if

  //le code ci-dessous bips de la sirène une fois par minute.
  currentMillis1 = millis();
  if (currentMillis1 - previousTime1 > interval1)
  {
    previousTime1 = currentMillis1;
    previousDelay1 = currentMillis1;
  }

  if (currentMillis1 - previousDelay1 > 100) {//100ms durée de chirp
  }

} //close countdown1();

/**********************************************************************
 *                        JEU2                                        *
 **********************************************************************/
void countdown2(){

 static unsigned long lastTick2 = 0; // mettre en place une variable locale pour maintenir la dernière fois que nous décrémentés une seconde
  static unsigned long currentMillis2 = 0;
  // (variables statiques sont initialisées une fois et conservent leurs valeurs entre les appels de fonction)
  // diminuer à une seconde tous 1000 millisecondes
  if (second2 > 0) {
    if (millis() - lastTick2 >= 1000) {
      lastTick2 = millis();
      second2--;
    }
  }
 // décrémenter une minute toutes les 60 secondes
  if (minute2 > 0) {
    if (second2 <= 0) {
      minute2--;
      second2 = 60; // remettre les secondes à 60
    }
  }
  // décrémenter une heure tous les 60 minutes
  if (hour2 > 0) {
    if (minute2 <= 0) {
      hour2--;
      minute2 = 60; // réinitialiser minutes à 60
    }//closes if
  }//closes if

  //le code ci-dessous bips de la sirène une fois par minute.
  currentMillis2 = millis();
  if (currentMillis2 - previousTime2 > interval1)
  {
    previousTime2 = currentMillis2;
    previousDelay2 = currentMillis2;
  }

  if (currentMillis2 - previousDelay2 > 100) {//100ms durée de chirp
  }

} //close countdown2();

/**********************************************************************
 *                        JEU3                                        *
 **********************************************************************/
void countdown3(){

 static unsigned long lastTick3 = 0; // mettre en place une variable locale pour maintenir la dernière fois que nous décrémentés une seconde
  static unsigned long currentMillis3 = 0;
  // (variables statiques sont initialisées une fois et conservent leurs valeurs entre les appels de fonction)
  // diminuer à une seconde tous 1000 millisecondes
  if (second3 > 0) {
    if (millis() - lastTick3 >= 1000) {
      lastTick3 = millis();
      second3--;

    }
  }
 // décrémenter une minute toutes les 60 secondes
  if (minute3 > 0) {
    if (second3 <= 0) {
      minute3--;
      second3 = 60; // remettre les secondes à 60
    }
  }
  // décrémenter une heure tous les 60 minutes
  if (hour3 > 0) {
    if (minute3 <= 0) {
      hour3--;
      minute3 = 60; // réinitialiser minutes à 60
    }//closes if
  }//closes if

  //le code ci-dessous bips de la sirène une fois par minute.
  currentMillis3 = millis();
  if (currentMillis3 - previousTime3 > interval1)
  {
    previousTime3 = currentMillis3;
    previousDelay3 = currentMillis3;
  }

  if (currentMillis3 - previousDelay3 > 100) {//100ms durée de chirp
  }
} //close countdown2();

That code is a mess. I'm sure you can refactor a lot of it. To get you started here's a C++ class you can use as a countdown timer. I just whipped this up, but it should work. However, it does not handle the case where millis() overflows (after about 50 days).
class Countdown {
public:
    const uint32_t ms_per_hour = 60l * 60l * 1000l;
    const uint32_t ms_per_minute = 60l * 1000l;
    const uint32_t ms_per_second = 1000l;

    // Constructor
    Countdown(int hours, int minutes, int seconds) {
        duration = hours * ms_per_hour +
                   minutes * ms_per_minute  +
                   seconds * ms_per_second ;
        started = false;
        finished = false;
    }
    // Call this to start the countdown
    void start() {
        started = true;
        finished = false;
        start_time = millis();
    }

    // Stop the timer
    void stop() {
        finished = true;
    }

    // Is timer running?
    bool is_running() {
        return started == true && finished == false;
    }

    // Call this to check if the countdown is finished
    bool times_up() {
        if (finished) return true;
        else if (!started) return false;
        if (elapsed_time() >= duration) {
            finished = true;
            return true;
        }
        return false;
    }

    // Returns a string representation of how much time has passed
    const char * get_elapsed(const char *format="hh:mm:ss") {
        return ms_to_string(format, elapsed_time());
    }
    // Returns a string representation of how much time is left
    const char * get_remaining(const char *format="hh:mm:ss") {
        return ms_to_string(format, duration - elapsed_time());
    }

    // Returns an array of decimal digits for display of time passed
    const char * get_digits_elapsed(const char *format="mmss") {
        return ms_to_digits(format, elapsed_time());
    }
    // Returns an array of decimal digits for display of time remaining
    const char * get_digits_remaining(const char *format="mmss") {
        return ms_to_digits(format, duration - elapsed_time());
    }

protected:
    unsigned long elapsed_time() {
        return millis() - start_time;
    }

    bool started, finished;
    uint32_t duration, start_time;
    char buffer[32];

    char * ms_to_digits(const char *format, uint32_t ms) {
        uint16_t hours = ms / ms_per_hour;
        ms %= ms_per_hour;
        uint16_t minutes = ms / ms_per_minute;
        ms %= ms_per_minute;
        uint16_t seconds= ms / ms_per_second;

        int index = 0;
        for (int i = 0; 0 != format[i]; i++) {
            if ('h' == format[i] || 'm' == format[i] || 's' == format[i]) {
                uint16_t val = 'h' == format[i] ? hours : ('m' == format[i] ? minutes : seconds);
                if (format[i] == format[i+1]) {
                    buffer[index++] = (char)(val / 10);
                    i += 1;
                }
                buffer[index++] = char(val % 10);
            }
        }
        return buffer;
    }

    char * ms_to_string(const char *format, uint32_t ms) {
        uint16_t hours = ms / ms_per_hour;
        ms %= ms_per_hour;
        uint16_t minutes = ms / ms_per_minute;
        ms %= ms_per_minute;
        uint16_t seconds= ms / ms_per_second;

        buffer[0] = 0;
        int index = 0;
        for (int i = 0; 0 != format[i]; i++) {
            if ('h' == format[i] || 'm' == format[i] || 's' == format[i]) {
                uint16_t val = 'h' == format[i] ? hours : ('m' == format[i] ? minutes : seconds);
                if (format[i] == format[i+1]) {
                    index += sprintf(&buffer[index], "%02d", val);
                    i += 1;
                }
                else {
                  index += sprintf(&buffer[index], "%d", val);
                }
            }
            else {
                buffer[index++] = format[i];
            }
        }
        buffer[index] = '\0';
        return buffer;
    }
};

To use it, you would create 3 objects:
Countdown cd1(0, 45, 0);  // 45 minutes
Countdown cd2(0, 15, 0);  // 15 minutes
Countdown cd3(0, 15, 0);  // 15 minutes

Then, start #1 in setup:
void setup() {
    cd1.start();
}

And in loop:
void loop() {
    if (cd3.times_up()) {
       // game over
    }
    else if (cd2.times_up()) {
        // 2nd timer expired, do something
        if (!cd3.is_running()) cd3.start();  // Start #3
        // update display
        tm1637d.display(c3.get_digits_remaining());
    }
    else if (cd1.times_up()) {
        // 1st timer expired, do something
        if (!cd2.is_running()) cd2.start();  // Start #2
        // update display
        tm1637c.display(c2.get_digits_remaining());
    }
    else {
        // update display
        tm1637b.display(c1.get_digits_remaining());
    }
}

You wrote: “it does not handle the case where millis() overflows”. Your code handles the millis() rollover perfectly fine.

@EdgarBonet Ah, yes. You are right. Thanks for pointing that out.

Thank you for you answer. I understand your code, but i don't know how to show countdown on the 4 digit display with that code.

And also how to stop a countdown with a   if (reading == LOW) but i'm going to try. Thank you !

@Fluti Ok, I added a function to return the time as an array of digits. Also, added a stop() function.