text:
Problem with SPI comms using NodeMCU v 3, Nano and SD
Recently I bought a NodeMCU 8266 v 3 (Lolin) and it works fine. I set up a Catalex SD card module (with a built-in 5-3.3V regulator) and all was good. Then I set the Lolin with an Arduino Uno and or a Nano working for SPI communications and all worked properly. So when I tried to put the Lolin as master, and two slaves (a Nano and an SD Card), all working with SPI, it did not work.
If I set up the SD card Vcc to 5 volts, the Lolin can "see" it and initializes it, but the communication between the Lolin and the Nano crashes (the Lolin can send the data but receives only trash; the Nano can receive and consequentely responds). When I disconnect the SD Vcc cable the communications works.
So I tried to remedy this situation using a bidirectional level shifter and the Lolin seems frozen.
Any help is welcome.

Code of Lolin (as Master).
/*Master - ESP12e create a variable string to be sent to slave - Nano_ChipSelect
    and receive a variable answer.

    Master ESP12e use:    COM5
          * SPI communications with a NANO as slave in GPIO 0 = D3
          * WiFi communication
          * a DS3231 for RTC
          * a catalex SD memory
*/

/*---------------( Import needed libraries )-------------------------------------*/
#include <ESP8266WiFi.h>                            // WiFi
#include <WiFiClientSecure.h>                       // SSL Client
#include <SPI.h>                                    // SPI comms
#include <SD.h>                                     // SD mem card
#include <Wire.h>                                   // RTC comms
#include "RtcDS3231.h"                              // RTC by maluma

/*---------------( Define Constants )--------------------------------------------*/
#define Nano_ChipSelect             D3              // Slave select signal for NANO
#define SD_ChipSelect               D8              // Slave select signal for SD

/*---------------( Declare objects )---------------------------------------------*/
RtcDS3231<TwoWire>    Rtc(Wire);
File                  myFile;
WiFiClientSecure      client;

/*---------------( Declare Special settings--------------------------------------*/
SPISettings           Set_SPI_NANO( 1000000, MSBFIRST, SPI_MODE0 );

/*---------------( Declare Constants )--------------------*/
String        defaultChatId         = "5";
char          ssid[]                = "scouts";     // network SSID (name)
char          password[]            = "R";   // network key

/*---------------( Declare Variables )-------------------------------------------*/
bool          switch_Red            = false;
bool          switch_Yell           = false;
bool          switch_Green          = false;
unsigned int  temp_ESP12e            = 0;
unsigned int  temp_nano             = 0;
unsigned int  hum_nano              = 0;
char          datestring[20];
char          Nano_S_to_send[]      = "0000000000000000000000000|";
//                                    "RRYYGcGYYYYcMMDDHcHMMSScc|"
//                                     01234567890123456789012345
//                                     0         1         2
char          Nano_S_to_receive []  = "0000000000000000000000000|";
//                                    "TTTTTcHHHHHcIIIIIcDDDDDcc|
//                                     01234567890123456789012345
//                                     0         1         2
byte          Leds                  = 0;

#define countof( a ) ( sizeof( a ) / sizeof( a[ 0 ] ) )

void _printDateTime( const RtcDateTime& dt ) {  //---------------------------------
    snprintf_P(datestring,
            countof(datestring),
            PSTR("%04u/%02u/%02u %02u:%02u:%02u"),
            dt.Year(),
            dt.Month(),
            dt.Day(),
            dt.Hour(),
            dt.Minute(),
            dt.Second() );
}

void _create_data_for_nano() {  //-------------------------------------------------
  RtcDateTime now = Rtc.GetDateTime();
  _printDateTime( now );
  //;
  //             RRYYGcGYYYYcMMDDHcHMMSScc|
  //             0000000000000000000000000|
  Nano_S_to_send[ 0 ] = _getbit( Leds, 0 );  // red status
  Nano_S_to_send[ 1 ] = _getbit( Leds, 1 );  // red status
  Nano_S_to_send[ 2 ] = _getbit( Leds, 2 );  // yellow status
  Nano_S_to_send[ 3 ] = _getbit( Leds, 3 );  // yellow status
  Nano_S_to_send[ 4 ] = _getbit( Leds, 4 );  // green status
  Nano_S_to_send[ 5 ] = _Nano_CRC( 0, 5 );
  Nano_S_to_send[ 6 ] = _getbit( Leds, 5 );  //green status
  Nano_S_to_send[ 7 ] = datestring[ 0 ];  //y
  Nano_S_to_send[ 8 ] = datestring[ 1 ];  //y
  Nano_S_to_send[ 9 ] = datestring[ 2 ];  //y
  Nano_S_to_send[ 10 ] = datestring[ 3 ];  //y
  Nano_S_to_send[ 11 ] = _Nano_CRC( 6, 5 );
  Nano_S_to_send[ 12 ] = datestring[ 5 ];  //m
  Nano_S_to_send[ 13 ] = datestring[ 6 ];  //m
  Nano_S_to_send[ 14 ] = datestring[ 8 ];  //d
  Nano_S_to_send[ 15 ] = datestring[ 9 ];  //d
  Nano_S_to_send[ 16 ] = datestring[ 11 ];  //h
  Nano_S_to_send[ 17 ] = _Nano_CRC( 12, 5 );
  Nano_S_to_send[ 18 ] = datestring[ 12 ];  //h
  Nano_S_to_send[ 19 ] = datestring[ 14 ];  //m
  Nano_S_to_send[ 20 ] = datestring[ 15 ];  //m
  Nano_S_to_send[ 21 ] = datestring[ 17 ];  //s
  Nano_S_to_send[ 22 ] = datestring[ 18 ];  //s
  Nano_S_to_send[ 23 ] = _Nano_CRC( 18, 5 );
  Nano_S_to_send[ 24 ] = _Nano_CRC( 0, 24 );
}

char _getbit( byte data, byte pos ){
  byte b = data >> pos;
  b = b & 1;
  char b1[] = { '0' };
  if( b ) b1[ 0 ] = '1';
  return b1[ 0 ];
}

char _Nano_CRC( byte pos, byte lon ) {  //---------------------------------------------
  int  suma = 0;
  bool par  = false;
  for( int i = 0 ; i < lon ; i++ ) {
    suma += char( Nano_S_to_send[ i + pos ] );
    if( par )  {
      suma += 2 * char( Nano_S_to_send[ i + pos ] );
    }
    par = !par;
  }
  int  b = suma/10;
  if( suma != b*10 )  b++;
  b *= 10;
  char resultado[ 2 ];
  itoa( b - suma, resultado, 10 );
  return resultado[ 0 ];
}

void _transfer_data_to_NANO_by_spi() {  //----------------------------------------
  char c[2];
  digitalWrite( SD_ChipSelect, HIGH );
  cli();
  byte index2 = 0;
  SPI.beginTransaction( Set_SPI_NANO );
  digitalWrite( Nano_ChipSelect, LOW );
  byte num_char_to_transfer = sizeof( Nano_S_to_send ) ;
  for( byte index = 0 ; index <= num_char_to_transfer ; index++ ) {
    c[ 1 ] = ( Nano_S_to_send[ index ] );
    c[ 0 ] = SPI.transfer( c[ 1 ] );
    if( index != num_char_to_transfer ) Nano_S_to_receive [ index2 ] = 'E';
    if( c[ 0 ] != '\0' ) {
      Nano_S_to_receive [ index2 ] = c[ 0 ];
    }
    if( index != 0 ) index2++;
    delayMicroseconds( 2 );
  }
  digitalWrite(Nano_ChipSelect, HIGH);
  //Serial.print("-->");Serial.print(Nano_S_to_receive);Serial.println("<--");
  sei();
  SPI.endTransaction ();
}

String _txt2str( int valor ){  //-------------------------------------------------
  char v_txt[]= "000";
  itoa( valor, v_txt, 10 );
  String v_text = "";
  for( int i = 0 ; i < 4 ; i++ ){
    if( v_txt[ 3-i ] != '\0' ) {
      v_text = v_txt[ 3-i ]+ v_text;
    }
  }
  return v_text;
}

int _convierte( byte pos ){  //---------------------------------------------------
    char temporal [] = "     ";
    for( int i = 0 ; i < 4 ; i++ )  {
      temporal [ i ] = Nano_S_to_receive [ i + 1 + pos ];
    }
    int temp = atoi( temporal);
    return temp;
}

void setup() {   /*-----------( SETUP: RUNS ONCE )------------------------------*/
  pinMode( SD_ChipSelect,   OUTPUT );          // configure the line as output
  pinMode( Nano_ChipSelect, OUTPUT );          // configure the line as output

  Serial.begin( 115200 );              // start the serial monitor
  digitalWrite( SD_ChipSelect,   HIGH );       // turn to HIGH to disable
  digitalWrite( Nano_ChipSelect, HIGH );       // turn to HIGH to disable slave

  Serial.println();
  Serial.print( "compiled: " );Serial.print( __DATE__ );
  Serial.print( " at " );Serial.println( __TIME__ );
  Serial.print( "Connecting Wifi: " );
  Serial.println( ssid );

  Rtc.Begin();

  RtcDateTime compiled = RtcDateTime( __DATE__, __TIME__ );
  RtcDateTime now = Rtc.GetDateTime();
  _printDateTime( now );
  Serial.print(" --- Initialized WiFi at ");
  Serial.println( datestring );

  if ( !Rtc.IsDateTimeValid() )   {
        Serial.println( "RTC lost confidence in the DateTime!" );
        Rtc.SetDateTime( compiled );
        RtcDateTime now = Rtc.GetDateTime();
        _printDateTime( now );
  }

  if( !Rtc.GetIsRunning() )  {
    Serial.println( "RTC was not actively running, starting now" );
    Rtc.SetIsRunning( true );
  }

   if ( now < compiled )     {
    Serial.println( "RTC is older than compile time!  (Updating DateTime)");
    Rtc.SetDateTime( compiled );
  } else if( now > compiled )    {
      Serial.println( "RTC is newer than compile time. (this is expected)" );
    } else if ( now == compiled )     {
        Serial.println( "RTC is the same as compile time!");
      }
  Rtc.Enable32kHzPin( false );
  Rtc.SetSquareWavePin( DS3231SquareWavePin_ModeNone );

  Serial.print( "Initializing SD card..." );

  SPI.begin();
  /* begin SPI at 1 Mbit rate most significat bit first & mode 0 */
  SPI.beginTransaction( SPISettings( 1000000, MSBFIRST, SPI_MODE0 ) );
  digitalWrite( SD_ChipSelect, LOW );

  if ( !SD.begin( SD_ChipSelect ) ) {
    Serial.println( "initialization failed!" );
    return;
  }
  myFile = SD.open( "Log_1.txt", FILE_WRITE );
  if (myFile) {                           // if the file opened okay, write to it:
    myFile.println( "YYYY:MM:DD:HH:MM:SS:TNANO:HNANO:TESP12e" );
    // close the file:
    myFile.close();
  } else {                             // if the file didn't open, print an error:
    Serial.println( "error opening file Log_1.txt" );
  }

  digitalWrite( SD_ChipSelect, HIGH );
  SPI.endTransaction();

  Serial.println( "*****  initialization done. ******" );
}

void loop() {  //-----------------------------------------------------------------

  Serial.println("*********** E S P 1 2 ***********");
  RtcTemperature temp = Rtc.GetTemperature();
  temp_ESP12e = temp.AsFloat() * 100;                         // System Temperature

  _create_data_for_nano();
  _transfer_data_to_NANO_by_spi();       // transfer routine to send and receive data
  //_check_received_data();

  Serial.print( "->NANO:" );Serial.print(    Nano_S_to_send );Serial.println(":");
  Serial.print( "NANO<-:" );Serial.print( Nano_S_to_receive );Serial.println(":");

  Leds++;
  if( Leds > 64 ) Leds = 0;
  delay(5000);
}

Code of nano ( as slave )
/* Slave - Nano receive a variable string, byte by byte from
 *  master - ESP12e and create a variable answer

      Slave NANO use:    COM3
           * SPI communications
           * an AM2302 sensor for temperature and humidity
           * timers
*/

/*---------------( Import needed libraries )-------------------------------------*/
#include <SPI.h>
#include <DHT.h>
#include "DHT_U.h"
#include "SimpleTimer.h"
#include "Adafruit_Sensor.h"

/*---------------( Define Constants )--------------------------------------------*/
#define switch_Yell       2
#define switch_Green      4
#define switch_Red        6
#define DHTPIN            9         // Pin connected to the DHT sensor.

#define DHTTYPE           DHT22     // DHT 22 (AM2302)

/*---------------( Declare objects )---------------------------------------------*/
SimpleTimer timer;
DHT_Unified dht(DHTPIN, DHTTYPE);

/*---------------( Declare Special settings--------------------------------------*/

/*---------------( Declare Constants )--------------------*/

/*---------------( Declare Variables )-------------------------------------------*/
uint32_t       waiting_for_AM2302;
char           string_to_receive[] = "0000000000000000000000000|";
//                                   "RRYYGcGYYYYcMMDDHcHMMSScc|"
//                                    01234567890123456789012345
//                                    0         1         2
char           string_to_answer[]  = "0000000000000000000000000|";
//                                   "TTTTTcHHHHHcIIIIIcDDDDDcc|
//                                    01234567890123456789012345
//                                    0         1         2
volatile byte  index;
volatile bool  receivedone;  /* used as reception complete flag */
byte           Dummy               = 0;

// function to be called repeatedly by timer function
void Read_AM2302() {  //-----------------------------------------------------------

  int tempera    = -1;
  int humidit    = -1;
  int illumin    = -1;
  int dummy       = -1;
  sensors_event_t event;
  // Get temperature event and print its value.
  dht.temperature().getEvent(&event);
  if (isnan(event.temperature)) {
    Serial.println("Error reading temperature!");
  }
  else {
    tempera = event.temperature * 10;
  }
  // Get humidity event and print its value.
  dht.humidity().getEvent(&event);
  if (isnan(event.relative_humidity)) {
    Serial.println("Error reading humidity!");
  }
  else {
    humidit = event.relative_humidity * 10;
  }

//  tempera = 9;
//  humidit = 72;
  illumin = 143;

  _create_answer( tempera,   0 );
  string_to_answer[  5 ] = _CRC(  0,  5 );
  _create_answer( humidit,      6 );
  string_to_answer[ 11 ] = _CRC(  6,  5 );
  _create_answer( illumin, 12 );
  string_to_answer[ 17 ] = _CRC( 12,  5 );
  //_create_answer( Dummy,       18 );
  string_to_answer[ 18 ] = _getbit( Dummy, 4 );
  string_to_answer[ 19 ] = _getbit( Dummy, 3 );
  string_to_answer[ 20 ] = _getbit( Dummy, 2 );
  string_to_answer[ 21 ] = _getbit( Dummy, 1 );
  string_to_answer[ 22 ] = _getbit( Dummy, 0 );
  string_to_answer[ 23 ] = _CRC( 18,  5 );
  string_to_answer[ 24 ] = _CRC(  0, 24 );
  /*
  Serial.print(" Temperature =");Serial.println( tempera );
  Serial.print(" Humidity     =");Serial.println( humidit );
  Serial.print(" Illumination =");Serial.println( illumin );
  Serial.print(" Dummy       =");Serial.println( Dummy   );
  Serial.print("Answer-->"); Serial.println( string_to_answer );
  */
}

char _getbit( byte data, byte pos ){
  byte b = data >> pos;
  b = b & 1;
  char b1[] = { '0' };
  if( b ) b1[ 0 ] = '1';
  return b1[ 0 ];
}

char _CRC( byte pos, byte lon ) {  //----------------------------------------------
  int  suma = 0;
  bool par  = false;
  for( int i = 0 ; i < lon ; i++ ) {
    suma += char( string_to_answer[ i + pos ] );
    if( par )  {
      suma += 2 * char( string_to_answer[ i + pos ] );
    }
    /*
    Serial.print(" i=");Serial.print(i);
    Serial.print(" d=");Serial.print(string_to_answer[ i + pos ] );
    Serial.print(" s=");Serial.println( suma);
    */
    par = !par;
  }
  int  b = suma/10;
  if( suma != b*10 ) b++;
  b *= 10;
  char result[ 2 ];
  itoa( b - suma, result, 10 );
  /*
  Serial.print( "-S-" );Serial.print( sum );      Serial.println("---");
  Serial.print( "-B-" );Serial.print( b );        Serial.println("---");
  Serial.print( "-R-" );Serial.print( result[ 0 ] );Serial.println("---");
  */
  return result[ 0 ];
}
                   //      9         0
void _create_answer( int data, byte pos) {  //-------------------------------------
  char temporal[] = {'\0','\0','\0','\0','\0'};  // masc
  byte longitud = 5;          // posicion desde 0 hasta n
  byte puntero = pos + longitud; //5
  itoa( data, temporal, 10 );//9
  //Serial.print("-t-");Serial.println( temporal );
  //Serial.print("-s-");Serial.println( sizeof temporal );
  for( int i = longitud ; i >= 0 ; i-- ) {
    //Serial.print("-val-");Serial.println( (temporal[i]) );
    if( temporal[i] != '\0' ) {
    string_to_answer[ puntero-- ] = temporal [ i ];
    }
  }
}

// SPI interrupt routine
ISR (SPI_STC_vect) {  //-----------------------------------------------------------
  uint8_t oldsrg = SREG;
  cli();
  string_to_receive[ index ] = SPDR;
  SPDR = string_to_answer[ index ];
  if( string_to_receive [index] == '\0' ) receivedone = true;
  if( index < sizeof( string_to_receive ) ) index++;
  sei();
  SREG = oldsrg;
}

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

  pinMode(MISO, OUTPUT);
  SPCR |= _BV(SPE);    // turn on SPI in slave mode
  SPCR |= _BV(SPIE);   // turn on interrupts

  index = 0;
  receivedone = false;
  SPI.attachInterrupt();    /* Attach SPI interrupt */
  dht.begin();
  sensor_t sensor;
  dht.temperature().getSensor(&sensor);
  dht.humidity().getSensor(&sensor);
  waiting_for_AM2302 = sensor.min_delay / 1000;
  Serial.println("------------------------------------");
  Serial.println("Temperature");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value);
  Serial.println(" *C");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value);
  Serial.println(" *C");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution);
  Serial.println(" *C");
  Serial.println("------------------------------------");
  Serial.println("Humidity");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value);
  Serial.println("%");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value);
  Serial.println("%");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution);
  Serial.println("%");
  Serial.println("------------------------------------");
  timer.setInterval( waiting_for_AM2302, Read_AM2302 );
  pinMode( switch_Red,   OUTPUT );
  pinMode( switch_Yell,  OUTPUT );
  pinMode( switch_Green, OUTPUT );
  digitalWrite( switch_Red,   LOW );
  digitalWrite( switch_Yell,  LOW );
  digitalWrite( switch_Green, LOW );

}

void loop () {  //-----------------------------------------------------------------
    timer.run();
  if (receivedone) {         /* Check and print received buffer if any */
    Serial.println( "************ N A N O ************" );
    Serial.print( "ESP12e<-:" );Serial.print( string_to_receive );Serial.println( ":" );
    Serial.print( "->ESP12e:" );Serial.print( string_to_answer );Serial.println( ":" );
    //_check_received_data();
    digitalWrite( switch_Red,   string_to_receive[ 1 ] - 48 );
    digitalWrite( switch_Yell,  string_to_receive[ 3 ] - 48 );
    digitalWrite( switch_Green, string_to_receive[ 6 ] - 48 );
    string_to_receive[index] = 0;
    index = 0;
    receivedone = false;

    Dummy++;
    if( Dummy > 32 ) Dummy = 0;
  }
}

here is the Serial monitor view
Master
    ******* L O L I N *******
    ->NANO:1111191201800204282452676|:
    NANO<-:000EEEEEEEE :                     --- connected at 5V
    ******* L O L I N *******
    ->NANO:0000080201810204282453192|:
    NANO<-:00<:
    ******* L O L I N *******
    ->NANO:0000080201810204282453642|:
    NANO<-:EEEEEEEEEEEEEEEEEEEEEE:          ---- connected at 3.3 V
    ******* L O L I N *******
    ->NANO:1000070201810204282454160|:
    NANO<-:0000990007250014320806510|:      ---- disconnected

Slave
    ************ N A N O ************
    LOLIN<-:1111191201800204282452676|
    ->LOLIN:0000990007250014320806510|
    ************ N A N O ************
    LOLIN<-:0000080201810204282453192|
    ->LOLIN:0000990007250014320806510|
    ************ N A N O ************
    LOLIN<-:0000080201810204282453642|
    ->LOLIN:0000990007250014320806510|
    ************ N A N O ************
    LOLIN<-:1000070201810204282454160|
    ->LOLIN:0000990007250014320806510|

how did you connect the Slave Select (SS, CS) pins

how are you getting 5v on the lolin board? (not from VIN).

Hi, I am getting the 5v from +5V pin of Nano or VV of Lolin, or as you can see in the picture both MCUs are together for test but when this work I´m going to put a power supply connected to Vin at both MCUs, and Vcc of the DS3231 and Catalex Sd card module.

For Nano I´m using D3 of Lolin, and for the SD I´m using D8 (Yellow wires). D1&D2 are for I2C comms with the RTC.

is the ground of lolin connected with ground of Nano?

Yes, in the picture the groud cable between Esp8266 and Nano is not showed, but I try at both forms and they are connected to the same PC by shielded USB cables

the USB didn't do a good ground connection in my SPI setup of Nano with Wemos

Use a tri-state buffer on the MISO pins of the SPI devices using the slave select as enable. It's the only way I could make it work.

Thank you, I was thinking the same, it is a hardware problem; I am waiting for a TI SN74LS07 ex buffer with and average propagation
delay time of 12 ns according its datasheet.

Hi jurag, dandavis and @sundayfantasy, updating my issue. The SD card has build-in an TI sn74lvc125a Quadruple Bus Buffer Gate With 3-State Outputs but for an unknow reason it never stop the MISO signal, so I just put a fairchild 4N35 and belive or not it is working fine. I´m waiting for a new SD and additional hardware to check what is happend here.

HI @sundaysfantasy, I just put a 4N35 and it is working

Good to know it works with an optocoupler too.


text:
ESP8266 as wifi Card?
I am very new to arduino and electronics in general. Can i use the NodeMcu Esp8266 as one of those usb wifi dongles? I want to use it as a monitor mode capable wifi card, for my linux laptop.

Yes. No. Maybe. What you want to do?

No, you can't. All you have is a UART interface through a USB to UART adaptor. It can only ever be a UART.
The best you could get would be to write a program to run on the NodeMCU that did the monitoring for you (assuming you can get it into a suitable promiscuous mode) and report information back to you through the UART.

source: Stack Exchange

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

sort: votes


text:
Why I'm getting this error: invalid conversion from 'const char*' to 'char' [-fpermissive]?
Why I'm getting this error?
invalid conversion from 'const char*' to 'char' [-fpermissive]
Here is my simple sketch:

const char data = "should";

//I have also tried:
//const char* data = "should";

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

void loop() {
  Serial.print("this " + data + " work");
}

No, it should not work this way. You are cofusing data types. char respresents a single character. So your first statement should be invalid. The second attempt looks reasonable but I'd use const char data[] instead. Now your string concatenation does not work at all because you are not using C++ Strings. Only those offer string concatenation with +.

the easy way in arduino:  Serial.print("this " + String(data) + " work");

const char data = "should";

In this case data is a single character, not a string. So it can store 's' but not "should".
Serial.print("this " + data + " work");

No, that will never work, even if you get your data types correct.  You do not concatenate strings like that. All you are doing is attempting to add the addresses of two string literals to the address of a string constant. If that were possible (the  compiler doesn't let  you) you'll get gibberish (or a crash) as it tries to print out whatever is at that address.
Instead break it down:
Serial.print("this ");
Serial.print(should);
Serial.print(" work");

You'll get gibberish as it tries to print out whatever is at that address. — no, you'll get compilation error. You can subtract pointers in C++, but not add.

@Ruslan Actually, in that specific instance you get a compilation error because the operands differ between a const char * for the variable and a const char[6] for the first literal. If you cast the literals as const char * you can subtract one and only one, otherwise you get differing arguments between the results of one subtraction (int) and the other string literal. The point I am making above though is that you do not concatenate strings by using +. Whether the syntax is "right" for something that is completely wrong anyway is neither here nor there.

You don't have to cast: the array will decay to a pointer before any arithmetic. But yes, the second subtraction would indeed cause an error because it'd try to subtract const char* from ptrdiff_t.

Ah yes, when subtracting it decays fine (as long as you only have one bit of arithmetic, otherwise you have to cast the result). When trying to (wrongly) add it doesn't decay, it just complains.

Operator overloading is a bad idea. This is one of them. How can a simple task (producing a string) need sam

Not sure what your saying there... Did you get truncated?

@Majenko. Damn entry box. Hit ENTER and voila. I edited it to a Wonderful comment and then lost it (5 minutes rule).

Thought as much. Been there, done that.

Anyway. Operator overloading: you need a CS degree and a copy of the 1,600 C++17 standard, plus access to the source code to be able to deduce what A+B does. Matters are further complicated by type promotions.

Let us continue this discussion in chat.

There's no operator overloading there.

A char can only store one character.
and const char* data can store a pointer to a string.
You can copy it with strcpy:
const char* data = malloc(7);
if (data != 0)
{
    strcpy(data, "should");
}

This will create 7 bytes, which can store "should" (adding 1 byte extra for the \0 byte to denote the end of a string.
However, in your case you can create a const string like:
const char data[7]="should";

or
const char data[]="should";

Tere is no space allocated that fits the string. :(

Added also memory check

Even now your code won't compile. And anyway, no point in using dynamic memory just to store a static string.

@Ruslan edited (this time compiled)

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

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


text:
Preventing relay switch-off crashing Ethernet controller
I have an Arduino Uno with Ethernet Shield controlling some relays. Initially everything works fine but then when switching the relay off, the Ethernet controller frequently 'crashes'. Ethernet stops responding to pings, although the Arduino Uno keeps running. Pressing the reset button brings the Ethernet controller back to life.
I am using three relays to control:

The 'Call for Heat' contact on the boiler (normally connected to a thermostat)
A Honeywell V4043 zone valve (6W / 0.42A)
A Grundfos UPS2 underfloor heating pump (0.06A - 0.42A)

This is my setup:

I am using 2N7002 MOSFETs to drive the relays
I have 1N4004 diodes across the coils

There is a circuit diagram for the 'Relay Driver Shield' part of the circuit here:
https://github.com/njh/relay-driver-shield
This is what I have done to attempt to solve the problem:

I have moved the Arduino + Ethernet further away from the relays
I switched to higher quality Omron Relays (G2R-1-S-DC12)
I have tried both Wiznet W5100 and ENC28J60 Ethernet controllers

But so far nothing has solved the problem.
Of the three relays, it appears to be the Honeywell V4043 zone valve that is causing the problem. While testing with no loads connected to the relays, it was working fine. My assumption is that the problem is related to discharges across the contacts, partly due to the inductive loads. But I am not sure what to do to fix it.
Thanks,
nick.

A schematic showing the connections will be very useful.

I'd start with optocoupler and separate power supply for the relay.

Sounds like you want some relay snubber circuits. And opto-isolation can't hurt either.

I have added a Block Diagram inline and a link to the relay driver circuit diagram on GitHub.

a 3300uf 10v "motherboard"capacitor "shorting" your 5v to ground might help.

I would suggest two things:

Use opto-isolators instead of (or as well as) the MOSFETs to control the relays, and
Add RC snubber circuits across the contacts.

The latter is the most important, since the spark across the contacts when they open will cause massive amounts of EMI.
The simplest circuit is a simple series resistor and capacitor placed across the contacts:

simulate this circuit – Schematic created using CircuitLab
Of course, ensure that the resistor and capacitor are rated for at least the voltage you are switching, preferably double.
Selecting the right values for the components depends very much on the load being switched and how much energy needs to be absorbed. I have shown ball-park figures that are usually "ok" for many situations.

Does the 1N4004 diodes across the coils not count?

No. Those are to absorb the back-EMF from the collapsing magnetic field in the relay coil. The snubber circuit is for the back-EMF from the inductive load that makes a massive spark across the relay contacts, both shortening the life of the relay, and making a massive EMI spike.

Thank you very much, I will give the RC snubber circuit a go.
In a previous version of the circuit, a cheap eBay 4-channel relay board, it did have an opto-isolater, but it doesn't seem to help. Would isolating the power lines (DC-DC isolated converter) help?

@Majenko. I see. Now, for the contact side a zero-current crossing detector will be really nice for switching off inductive loads.

Note that you need a mains rated capacitor. I think they are called class X capacitors, but please don't trust me on that one.

I bought some encapsulated RC RE12001 snubbers on eBay to protect the contacts on each of the relays. They are 0.01uF / 120Ω. Since fitting them, it hasn't crashed once :-) Thanks! I have uploaded a photo of it to GitHub.


text:
Will adding Ethernet shield reduce the IO count of Arduino?
I have searched this question but could not find an answer on this site.
There was a related question - Latest Ethernet shield - used pins, how to bypass restrictions on arduino forums, but, I was unable to understand what the answer meant.
The background of my project:
My project requires

| S.No. | IO Type | IO Qty |
|-------+---------+--------|
| 1     | AI      |     11 |
| 2     | DI      |      9 |
| 3     | DO      |     11 |

I intend to connect this arduino board via ethernet shield to a network. I want to receive data over the network for display and storage purposes on a PC.
Questions:

What Arduino board should I select?
Will ESP8266 be compatiable with the suggested model?
Are there any pitfalls that should be considered when making the
selection for this design.

P.S: I have raised the same question on the arduino forum. If I get an answer- I will share my answer here as well

@Juraj. I understand that [Mega2560] has the most number of IO's. 16-AI and 54 DI/DO. Should that be ok?

click the link to the "related question" and you will find that it invalid.

@jsotola Its funny, that the link broke. Fixed it

instead of posting the same thing on two websites, post a description here of what you do not understand. ... someone here may be able to give you an explanation. ... the way things are, you may get an answer, but your understanding will still be unclear.

You should use a Mega if you really need so many gpio pins.
Arduino Ethernet and WiFi shields and their clones use 3 GPIO pins with SPI function with connection on ICSP header. Next they use the Slave Select signaling pin 10 and the SD card Slave Select signaling pin 4. The shields are compatible with Mega. So you should still have enough pins.
esp8266 can be connected to SPI. then it uses the same pins like the Ethernet shield except of the SD card slave select pin.
if you connect esp8266 to Serial port, then all the pins are free. Mega has 4 Serials.
esp8266 is cheaper but you need to connect it with level shifters and have a good power supply. there is no good esp8266 shield for now. The Mega + WiFi board from Robotdyn has the esp8266 on board with Serial connection.

SPI function is on pins 11, 12, 13 on Uno and 50, 51, 52 on Mega. the Slave Select (SS) pin is SPI function if Atmega is SPI slave. 10 on Uno and 53 on Mega. If Atmega is master, then the SS pin must be set as output. So it is good to use it for signaling to SS pin of one of the slaves.


text:
What causes Serial.available() to become false after Serial.read() gets data?
As serial data bytes are being read from the serial buffer by Serial.read(), are they removed from the Arduino's 64-byte serial buffer altogether?
In my current situation I'm using SoftwareSerial, but this question applies to both software and hardware serial connections.
EDIT: Based on a comment from @dandavis, I'd like to further clarify my question
How does Serial.read() interact with Serial.available()? Let's say that I have the usual setup:
while( Serial.available() ) {
    Serial.read();
}

What causes Serial.available() to become false?
EDIT 2: Changed question title for even further clarification...

the only way you can "remove" a byte, is to overwrite it. ... i do not think that the library code does that, because that would be a waste of resources. ... i'm sure that the pointer into the buffer is the only thing that has changed.

yes, you read() until available() is false, at which point the buffer is considered empty.

What do you mean by "removed"?

See the Wikipedia article Circular buffer. It has some figures and an animation that should help you understand how it works.

If they weren't, you would only ever be able to receive 64 bytes. Does that sound logical?

@dandavis Thank you for that clarification - That was pretty much what I was asking, but couldn't figure out how to ask (terribly sorry).I suppose it would have been best to phrase the question as 'How does Serial.available() go from true to false?

Calculating how many bytes are available for reading:
int HardwareSerial::available(void)
{
  return ((unsigned int)(SERIAL_RX_BUFFER_SIZE + _rx_buffer_head - _rx_buffer_tail))
}

It's so simple.
Have a look at the Arduino subdir (in your disk) hardware/arduino/avr/cores/arduino. The HardwareSerial.cpp is where you have to look at.

It is an internal buffer and only the pointer gets increased. It it visible in the source code off the project, located on github:
// Read data from buffer
int SoftwareSerial::read()
{
  if (!isListening())
    return -1;

  // Empty buffer?
  if (_receive_buffer_head == _receive_buffer_tail)
    return -1;

  // Read from "head"
  uint8_t d = _receive_buffer[_receive_buffer_head]; // grab next byte
  _receive_buffer_head = (_receive_buffer_head + 1) % _SS_MAX_RX_BUFF;
  return d;
}

This third line from the bottom is the important part, it wraps back to the beginning if the buffer space has run out. If you call Serial.read(), the pointer is moved to the next position. So with the next Serial.read(), you'll get the next byte, if available. The byte itself gets overwritten only after the wrap (circular buffer).

That's call a circular buffer.

You wrote: “The byte itself gets never overwritten”. It does, eventually, when that buffer cell is reused for storing a new incoming byte.

@EdgarBonet. The moment the pointer advanced, the byte disappears, it's not longer there, it doesn't exists anymore from the perspective of the running code.


text:
SPI - Apparently Random pulses on CS/SS line
I'm trying to figure out why my SPI device isn't responding as expected. So I hooked up my logic analyzer and am a bit confused by the results.
I'm seeing what appears to be random pulses on the chip select/slave select line (CS in the images below). The pulses happen in random locations with random counts. Always matching either a falling edge or rising edge in the CLK line.

The code I'm running is part of a library, but I've pulled it all out for a minimum functional example:
#include <SPI.h>

#define DC_PIN          9
#define CS_PIN          10
#define BUSY_PIN        7

int IfInit(void) {
    pinMode(CS_PIN, OUTPUT);
    SPI.begin();
    SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
    return 0;
}

void SpiTransfer(unsigned char data) {
    digitalWrite(CS_PIN, LOW);
    SPI.transfer(data);
    digitalWrite(CS_PIN, HIGH);
}

int Init() {

    if (IfInit() != 0) {
        return -1;
    }

    SendCommand(0x01); //POWER_SETTING
    SendData(0x03);                  // VDS_EN, VDG_EN
    SendData(0x00);                  // VCOM_HV, VGHL_LV[1], VGHL_LV[0]
    SendData(0x2b);                  // VDH
    SendData(0x2b);                  // VDL
    SendData(0xff);                  // VDHR
    SendCommand(0x06); //BOOSTER_SOFT_START
    SendData(0x17);
    SendData(0x17);
    SendData(0x17);                  //07 0f 17 1f 27 2F 37 2f
    SendCommand(0x04); //POWER_ON
    WaitUntilIdle();
    SendCommand(0x00); //PANEL_SETTING
    SendData(0xbf);    // KW-BF   KWR-AF  BWROTP 0f
    SendData(0x0b);
    SendCommand(0x30); //PLL_CONTROL
    SendData(0x3c);        // 3A 100HZ   29 150Hz 39 200HZ  31 171HZ

    return 0;
}

void SendCommand(unsigned char command) {
//    digitalWrite(DC_PIN, LOW);
    SpiTransfer(command);
}

void SendData(unsigned char data) {
//    digitalWrite(DC_PIN, HIGH);
    SpiTransfer(data);
}

void WaitUntilIdle(void) {
    while(digitalRead(BUSY_PIN) == 0) {      //0: busy, 1: idle
        delay(100);
    }
}

void setup() {

  pinMode(CS_PIN, OUTPUT);
  digitalWrite(CS_PIN, HIGH);

  Serial.begin(9600);
  Serial.println("Start");

  if (Init() != 0) {
    Serial.println("init failed");
    return;
  }

  Serial.print("init success");

}

void loop() {

}

I've tried on two different ATMEGA chips (same Arduino Uno board), same results. I've also tried with the device disconnected. Again same results. I've also tried changing the pin used for the CS, still didn't change anything.
Anyone have some insight as to what might be causing this, and/or what can be done to stop it?

ground is connected?

What processor (Arduino board) are you using?

Doing SPI.begin() after SPI.beginTransaction is the wrong order to do things. SPI.begin() should be done first.

Yes each test line of the logic analyzer is grounded.

@NickGammon That is how the library had it, nonetheless I believe you are correct. I have updated the code, re-ran the test, however the issue persists.

@NickGammon Running on Arudino Uno (Official)

The leads from arduino to device are about 15 inches. Is that long enough to be affected by RF?

ground between Uno and the device is connected?

I shortened the leads between my arduino board and the device from 15 inches down to ~5 inches and the issue disappeared.
I would have to guess that it was some RF interference.

Interesting. A possible alternative would have been to slow down SPI. However that doesn't totally explain the glitches on SS.

See my page about SPI.

Pin 10 of the Arduino is the SS line - so does this mean you have to use it for the peripheral SS line? Or should it be kept high? The answer (from the Atmega documentation) is that the SS line (pin 10) must be configured as an output (regardless of what value is on it). If configured as an output the Arduino ignores the value on that line, and thus the SPI hardware will not be put into slave mode.
Since the value on pin 10 is ignored, providing it is set as an output, then it can also be used as the SS line for your first, or only, slave. You could then use other pins (eg. 5, 6, 7, 8, 9) to control other slaves.

For you to successfully make an SPI master then pin 10 on your Uno must be configured as an output, regardless of whether or not you actually use pin 10 for SS. Under the circumstances, you may as well use pin 10 for SS if you are going to make it an output anyway.

This issue persists when using pin 10 as the SS.

I tried your code with my Uno (no device connected) and had no such problems. Sounds like an electrical issue to me.

This issue persists when using pin 10 as the SS.

See amended reply. I cannot reproduce that issue with your code.

Interesting. That definitely suggests it's an issue specific to my setup. Thanks.


text:
SD begin affecting OLED display
Okay, I'm using u8g2 library for my OLED display. After calling SD.begin(4) function, I cannot display anything on my OLED.
I'm using U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); constructor from u8g2 library since I'm using I²C for the display and SPI for microSD reader. I removed the CS Pin 4 from SD.begin() and I can now display something on the OLED.
How did supplying CS Pin parameter to SD.begin() function affected the I²C OLED display?

Pins 4 and 5 are the I2C pins that belong to the built in I2C peripheral on the Arduino. You have to put your CS line for the SPI SD card on a different pin.
EDIT:
The answer above is relevant to the Arduino ATMega328-based board, not ESP8266-based NodeMCU board. This answer is not relevant to ESP8266 or NodeMCU with regard to hardware I2C, as the ESP8266 does not have a dedicated hardware I2C peripheral.

I'm using ESP8266 (NodeMCU v3) and pin numbers for I2C is D1 & D2 (printed on the board). Man, this caused confusion to me. Thanks for the explanation.

The NodeMCU docs say to use Pin 8 for SPI (SD Card) slave-select.


text:
NodeMCU doesn’t send the sensor read while powering with Vin
I have connected a NodeMCU ESP 12 with the Vin (6 volts) shared with 2 other NodeMCU. The sensors are getting power from the NodeMCU but the NodeMCU isn’t sending to the ThingSpeak cloud unless I plugged it to the PC and unplug the Vin.
Help please.

What is your power supply? AA batteries? Wall adaptor?

Four of AA battery @LookAlterno

Have a look at this question: https://arduino.stackexchange.com/questions/37641/nodemcu-power-consumption-measurement-and-deepsleep

@LookAlterno I didn’t understand that topic

It looks like 4 AA batteries doesn't have enough juice to power 3 NodeMCU + sensors. Try with a battery pack, if you had one.

@LookAlterno I tried to power only one nodemcu and nothing changed

Edit your question and add a schematic (draw by hand on paper). The three NodeMCU must be connect in parallel: GND to GND, 3.3V to 3.3V.

@LookAlterno  check it now please

You must connect together all devices by their GND pin.

@LookAlterno thanks a lot dude ! Now it’s work!

You must connect together all devices by their GND pin.


text:
How do I lower clock speed for MKR1000?
According to data sheets, the MKR1000 runs a SAMD21 Cortex-M0+ processor at 48 MHz. For a project I need to drop that down to 16MHz to get some accurate timing in us. How can I do this? Most of the suggestions on the internet involve the ATmega* boards.
Thanks in advance.

Because I'm interfacing with external hardware that can only handle 16MHz.

add the comment about interfacing 16MHz to your question, then delete your comment. ... replace the to get some accurate timing in us with the reference to external hardware .... i am deleting my comments.

48 MHz is a multiple of 16MHz. Why not just adjust the timing code to account?

As noted above, I am not certain this will work, because I'm interfacing with some external hardware whose max speed is 16MHz. I'm trying to slow down for that. Maybe I need some artificial delays inserted, then?

Elaborate on your external hardware, then.


text:
Nodemcu connecting to Wi-Fi Problem
I am trying to connect to Wi-Fi with Digital pin declaration in setup() function it's not connecting to wi-fi. But connecting to wi-fi without digital pin diclaration. `
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
int m1 = 5;
int m2 = 6;
const char* ssid = "KS Infotech";
const char* password = "kalamsalam";
String readc = "";
void setup () {
pinMode(m1, OUTPUT);
digitalWrite(m1, LOW);
pinMode(m2, OUTPUT);
digitalWrite(m2, LOW);
Serial.begin(9600);
WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {

delay(1000);
Serial.print("Connecting..");

}

}

void loop() {
while (Serial.available()){  //Check if there is an available byte to read
delay(10); //Delay added to make thing stable
char c = Serial.read();
String T = String(readc);
    Serial.println(T);
if (WiFi.status() == WL_CONNECTED) { //Check WiFi connection status

HTTPClient http;  //Declare an object of class HTTPClient

http.begin("http://ksinfotech.co/kslab/write_to_database.php?incoming="+T+"&UID=surya");  //Specify request destination
int httpCode = http.GET();

if (httpCode > 0) { //Check the returning code

  String payload = http.getString();   //Get the request response payload
  Serial.println(payload);                     //Print the response payload
  if (payload == 'N');
  {
  digitalWrite(m1, HIGH);
  digitalWrite(m2, LOW);
  delay(2000);
  digitalWrite(m1, LOW);
  digitalWrite(m1, LOW);
}
      if (payload == 'F');
  {
  digitalWrite(m1, LOW);
  digitalWrite(m2, HIGH);
  delay(2000);
  digitalWrite(m1, LOW);
  digitalWrite(m1, LOW);
}

http.end();   //Close connection

}

delay(30000);    //Send a request every 30 seconds

}

The above code not working but the below code working.
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>

const char* ssid = "KS Infotech";
const char* password = "kalamsalam";
String readc = "";
void setup () {

Serial.begin(9600);
WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {

delay(1000);
Serial.print("Connecting..");

}

}

void loop() {
while (Serial.available()){  //Check if there is an available byte to read
delay(10); //Delay added to make thing stable
char c = Serial.read();
if (c == '#'){
  break;                   //Stop the loop once # is detected after a word
}//Conduct a serial read
readc += c; //build the string- "forward", "reverse", "left" and "right"
}
String T = String(readc);
    Serial.println(T);
if (WiFi.status() == WL_CONNECTED) { //Check WiFi connection status

HTTPClient http;  //Declare an object of class HTTPClient

http.begin("http://ksinfotech.co/kslab/write_to_database.php?incoming="+T+"&UID=surya");  //Specify request destination
int httpCode = http.GET();
 //Send the request

if (httpCode > 0) { //Check the returning code

  String payload = http.getString();   //Get the request response payload
  Serial.println(payload);                     //Print the response payload

}

http.end();   //Close connection

}

delay(30000);    //Send a request every 30 seconds

}

Pins 5 and 6 are not what you think they are. 5 != D5 6 != D6

posted on arduino forum http://forum.arduino.cc/index.php?topic=527272

Lack of formatting makes your code very hard to read. Use the format tools available in Arduino IDE

Thanks for your answers and suggestions. My problem solved.

use D5 and D6, not 5 and 6. D5 is IO 14, D6 is IO 12. IO 5 is D1 and IO 6 is SDIO_CLK for the flash memory and that is your problem.
the reference

I think GPIO06 is connected to flash and that's why it fails.

yes. I edited the answer. it is is SDIO_CLK for the flash memory

but pin5 is the best pin on board, tied with pin4...

then please mark the answer as accepted


text:
Ethernet connection - how to send data from interrupt
I have question similar to old topic here Any way to pass EthernetClient to function outside of loop automatically?
I have in the main loop opening of the TCP server which is just maintaining the connection, but I need to send data from the interrupt rutine.
Can anybody tel me how to declare the connection globaly to be able to reference from event rutine and not from main loop only?
Thank you

That's probably a bad idea - this is far too involved and lengthy a task to safely perform in an ISR.  What you should do is set a volatile flag in the ISR to indicate to the main program loop that it would be appropriate to send some data.

use globals to store the data to be sent, and a flag that indicates data is ready, then check the global in loop() and response accordingly; it won't take a lot of extra time...

I need to stream data as much synchronous as possible so I'm looking for a way how to send it from ISR directly. Thanks anyway.

@jantkany - then you shouldn't be using TCP to begin with.   Doing this in an ISR is not going to work, and the delay of doing it in the main loop will be well within the norms of TCP traffic, if your program is well structured.

No surgery in the dr's office, you get the diagnosis and schedule an appt with a surgeon.

You don't, instead you set a volatile flag in the interrupt routine and/or append to a circular buffer and handle the actual sending the next time through in your main loop.
The time delay from deferring action from the ISR to the main loop code will be on the order of milliseconds, if that.


text:
Synching local clock usign NTP to milliseconds
I am interested in getting a local clock on an ESP32 module synch to
a network clock using NTP. I am able to read data and time here. But I am interested in synching to the milli second level.
    #include <WiFi.h>
    #include <WiFiUdp.h>

    char ssid[] = "*************"; //  your network SSID (name)
    char pass[] = "********"; // your network password

    unsigned int localPort = 2390; // local port to listen for UDP packets

    IPAddress timeServerIP; // time.nist.gov NTP server address
    const char* ntpServerName = "time.nist.gov";

    const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes
    byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing
    // A UDP instance to let us send and receive packets over UDP
    WiFiUDP udp;

    void setup() {
      Serial.begin(115200);
      Serial.println();
      Serial.println();
      // We start by connecting to a WiFi network
      Serial.print("Connecting to ");
      Serial.println(ssid);
      WiFi.begin(ssid, pass);
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
      }
      Serial.println("");
      Serial.println("WiFi connected");
      Serial.println("IP address: ");
      Serial.println(WiFi.localIP());
      Serial.println("Starting UDP");
      udp.begin(localPort);
      Serial.print("Local port: ");
    }

    void loop() {
      //get a random server from the pool
      WiFi.hostByName(ntpServerName, timeServerIP);
      sendNTPpacket(timeServerIP);
      // send an NTP packet to a time server
      // wait to see if a reply is available
      delay(1000);
      int cb = udp.parsePacket();
      if (!cb) {
        Serial.println("no packet yet");
      } else {
        Serial.print("packet received, length=");
        Serial.println(cb);
        // We've received a packet, read the data from it
        udp.read(packetBuffer, NTP_PACKET_SIZE);
        // read the packet into the buf
        unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
        unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
        // combine the four bytes (two words) into a long integer
        // this is NTP time (seconds since Jan 1 1900):
        unsigned long secsSince1900 = highWord << 16 | lowWord;
        Serial.print("Seconds since Jan 1 1900 = " );
        Serial.println(secsSince1900);
        unsigned long mshighWord = word(packetBuffer[44], packetBuffer[45]);
        unsigned long mslowWord = word(packetBuffer[46], packetBuffer[47]);
        unsigned long mssecs = mshighWord << 16 | mslowWord;
        Serial.print("Frac Seconds = " );
        Serial.println(mssecs);
        // now convert NTP time into everyday time:
        Serial.print("Unix time = ");
        // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
        const unsigned long seventyYears = 2208988800UL;
        // subtract seventy years:
        unsigned long epoch = secsSince1900 - seventyYears;
        // print Unix time:
        Serial.println(epoch);
        // print the hour, minute and second:
        Serial.print("The UTC time is "); // UTC is the time at GMT
        Serial.print((epoch  % 86400L) / 3600);
        // print the hour (86400 equals secs per day)
        Serial.print(':');
        if (((epoch % 3600) / 60) < 10) {
          // In the first 10 minutes of each hour, we'll want a leading '0'
          Serial.print('0');
        }
        Serial.print((epoch  % 3600) / 60); // print the minute
        Serial.print(':');
        if ((epoch % 60) < 10) {
          // In the first 10 seconds of each minute, we'll want a leading '0'
          Serial.print('0');
        }
        Serial.println(epoch % 60); // print the second
      }
      // wait ten seconds before asking for the time again
      delay(10000);
    }

    // send an NTP request to the time server at the given address
    unsigned long sendNTPpacket(IPAddress& address) {
      Serial.println("sending NTP packet...");
      // set all bytes in the buffer to 0
      memset(packetBuffer, 0, NTP_PACKET_SIZE);
      // Initialize values needed to form NTP request
      // (see URL above for details on the packets)
      packetBuffer[0] = 0b11100011; // LI, Version, Mode
      packetBuffer[1] = 0; // Stratum, or type of clock
      packetBuffer[2] = 6; // Polling Interval
      packetBuffer[3] = 0xEC; // Peer Clock Precision
      // 8 bytes of zero for Root Delay & Root Dispersion
      packetBuffer[12]  = 49;
      packetBuffer[13]  = 0x4E;
      packetBuffer[14]  = 49;
      packetBuffer[15]  = 52;
      // all NTP fields have been given values, now
      // you can send a packet requesting a timestamp:
      udp.beginPacket(address, 123); //NTP requests are to port 123
      udp.write(packetBuffer, NTP_PACKET_SIZE);
      udp.endPacket();

And your question is?

its not clear exactly how the fractional part of the seconds field is read from the NTP UDP packet. Here I have the code that reads the 4 bytes after seconds
unsigned long mshighWord = word(packetBuffer[44], packetBuffer[45]);
unsigned long mslowWord = word(packetBuffer[46], packetBuffer[47]);
unsigned long mssecs = mshighWord << 16 | mslowWord;
Serial.print("Frac Seconds = " );
Serial.println(mssecs);

Coding is hard enough, and its even harder if you put just like a sentence. If you have additional information, you can edit your question and put it there so that its easier to read and easier to notice.

hi dhimaspw..understood..newbie here. Wasnt sure how to add code to the comment box

The NTP timestamp format doesn't use milliseconds. All timestamps are in
seconds, in a 32.32 fixed point format. This means that the
fraction field is in units of 2−32 s, or about
233 picoseconds. You can convert that to milliseconds by
multiplying by 1000 and dividing by 232. For example:
uint32_t frac  = (uint32_t) packetBuffer[44] << 24
               | (uint32_t) packetBuffer[45] << 16
               | (uint32_t) packetBuffer[46] <<  8
               | (uint32_t) packetBuffer[47] <<  0;
uint16_t mssec = ((uint64_t) frac * 1000) >> 32;

If you want to avoid 64-bit arithmetic, you can instead divide by 128,
then multiply by 125, then divide by 222:
uint16_t mssec = ((frac >> 7) * 125) >> 22;

That should give the same result except for a potentially larger
rounding error. Note that, if you care about rounding, you would try to
round to nearest rather than towards zero:
uint16_t mssec = ((frac >> 7) * 125 + (1UL << 21)) >> 22;

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


text:
How to control an 12V 2A Car lamp using relay or MOSFET in Arduino
I am working with the project controlling an 25W 12V Car lamp. I have a 12V car battery. I want to control it with the Arduino using a relay or MOSFET.
Any suggestion for my project would be appreciated.

You do it the same way as any other kind of light control. "Car" makes no difference.

But arduino output draws only minimum amount of current for 25W 12v lamp the current rating should 1.75A how to boost up the current to make the lamp ON

You already answered that in your question - use a MOSFET or a relay.

You can use a RFP30N06LE mosfet. It can support up to 60V 30A
Here is a wiring schema

and one more doubt....is ground can be common for different current rated loads....Example i am using 12v car battery in that load side i have 5W and 21W lamps can i connect ground of these 2 common....because i am using ground switching for output....supply is directly given to all lamps...

Ground have to be common. It won't works if they are not connected each other


text:
How can I make an AC analog voltage with Arduino?
I am trying to create an AC voltage in Arduino. Until now I have only managed to get a square wave. How can this be achieved with Arduino?
If I try:
int up;
int down;
int out = 11;

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

void loop() {
  for (up = 0; up <= 255; up++) {
    analogWrite(out, up);
    delay(1);
  }
  for (down = 255; down >= 0; down--) {
    analogWrite(out, down);
    delay(1);
  }
}

is it still pulsed DC?

Yes, it is still a square wave, varying between 0V and 5V. You need some extra hardware to do that.

What kind of frequency are you looking for? Do you want a sinewave, triangle wave, saw-tooth wave ... ?

just use an opamp to turn your square wave into a sine wave with a few caps and resistors

You have a few options:

Use a low-pass filter to round the square wave's edges some so they look more AC-ish.
Use a low-pass filter and have your code create steps of voltage that look AC-ish by varying the PWM widths.
Use an external SPI DAC chip that you can control with more discrete levels to make smoother looking AC.
Look into Direct Digital Synthesis (DDC) to learn more. Google "analog via ddS", lots of hits.


text:
Why connect a diode between the reset pin of Arduino and 555 timer?
I am trying to create a watchdog timer using 555 IC and I am following this.
I do not understand why a 1N4148 diode is connected between the reset pin of Arduino and the output of the 555 timer.

As far as I understand, the reset pin of the Arduino should be high, and when it is pulled low, the Arduino resets. But why should we add a diode over here? What purpose does it serve?

After reading @Majenko's answer, I can see how your schematic would not have made it obvious since it doesn't show any of the other connections on a typical Arduino.

Yeah. And that was the reason, why I did not understand the use of the diode over there.

It's called a "Wired Or" arrangement.
The Arduino's RESET pin has a pullup resistor in it (10KΩ). That keeps the RESET pin normally HIGH. To invoke a reset that pin needs pulling low, and that is done from a number of sources:

The RESET button
The DTR pin (through a 100nF capacitor) of the USB interface chip
The 555 watchdog circuit above

The critical one there is the DTR pin.  That, because it's a brief pulse with quite a high output impedance, needs the reset pin to be easy to pull down. If you connected the output of the 555 directly to RESET it would be constantly trying to pull the RESET pin up to 5V with quite a low output impedance. The DTR circuit would have no chance of overcoming it.
So by adding a diode in there you get Wired Or, using an arrangement direct from the 1950s - DRL - Diode-Resistor Logic.  When the output of the 555 is HIGH the diode is reverse biased (or neutrally biased) and doesn't conduct, so the RESET pin's own resistor pulls the RESET pin up.  However, when the output of the 555 is LOW the diode can then conduct (it's forward biased) and that pulls the RESET pin LOW.

Thanks for the information @Majenko. It was really helpful. I have a small confusion. The RESET pin is not a source of voltage or current, right? So how does the RESET pin become LOW as soon as the 555 is low with the diode conducting? I mean how does current flow from the RESET pin if its not a source of current?

Yes, it is a source of voltage and current. It is connected to +5V through a 10K resistor. Connect it to ground and (5/10,000) 5uA will flow from it to ground.

Every pin is either a source or sink (or both) of current. It's all a matter of how much current (the output impedance) the pin can sink or source.


text:
How to make timed loops after switch / case?
I am working on a code, which is running a function once a second:
switch (gearbox1) {
  case 1:
    //manually close
    Serial.println("Closing1");
    digitalWrite(gear1OpenPin, OFF);
    t.setTimer(1000, Close1, 1);

    break;

  case 2:
    //manually open
    Serial.println("Opening1");
    digitalWrite(gear1ClosePin, OFF);
    t.setTimer(1000, Open1, 1);

    break;

This part is working fine. But then i want at case 10: call function autoClose() which would work in 10 second cycles.
Struggle is, as my first function is called once a second, it is starting function autoClose() once a second as well. How can I overcome this please?
At the moment I have current, non working code:
  case 10:
    //automatic close
    Serial.println("A Close1");
    digitalWrite(gear1ClosePin, OFF);
    digitalWrite(gear1OpenPin, OFF);

    t.enable(autoClose);
    autoClose();
    break;

Edit: Added minimal possible code. I want autoOpen() and autoClose() to loop in 10 sec. intervals.
#include <SimpleTimer.h>
SimpleTimer t;
int gearbox1;

#define gear1OpenPin 44
#define gear1ClosePin 46

int OFF = HIGH;  // states for relays
int ON = LOW;

byte gear1Open = 0;
byte gear1Close = 0;

void setup() {

  t.setInterval(1000, Control1);
  int autoOpen = t.setInterval(10000, autoOpen);
  int autoClose = t.setInterval(10000, autoClose);
}

void loop() {

  t.run();
}

void Control1() {
  //*****************************************
  switch (gearbox1) {
    case 1:
      //manually close
      Serial.println("Closing");
      digitalWrite(gear1OpenPin, OFF);
      t.setTimer(1000, Close1, 1);

      break;

    case 2:
      //manually open
      //   Serial.println("Opening");
      digitalWrite(gear1ClosePin, OFF);
      t.setTimer(1000, Open1, 1);

      break;

    case 5:
      //stop
      Serial.println("Stopping");
      digitalWrite(gear1ClosePin, OFF);
      digitalWrite(gear1OpenPin, OFF);

      break;

    case 10:
      //automatic close

      digitalWrite(gear1ClosePin, OFF);
      digitalWrite(gear1OpenPin, OFF);
      if (t.isEnabled(autoClose)) {
        autoClose();
      } else {
        t.restartTimer(autoClose) ; t.enable(autoClose);
        autoClose();
      }
      break;

    case 20:
      //automatic open

      digitalWrite(gear1ClosePin, OFF);
      digitalWrite(gear1OpenPin, OFF);
      t.restartTimer(autoOpen); t.enable(autoOpen);
      autoOpen();
      break;
 }
}

void Open1() {
  digitalWrite(gear1OpenPin, ON);
}
//**********************************************
void Close1() {
  digitalWrite(gear1ClosePin, ON);
}
//**********************************************
void autoOpen() {

  if (gear1Open == ON) {
    gear1Open = OFF;
  } else {
    gear1Open = ON;
  }
  digitalWrite(gear1OpenPin, gear1Open);
}
//**********************************************
void autoClose() {
  if (gear1Close == ON) {
    gear1Close = OFF;
  } else {
    gear1Close = ON;
  }
  digitalWrite(gear1ClosePin, gear1Close);
}

You don't show Auto() function being called at all, yet you state it is starting once per second. Show all your code, or at least a complete working example that demonstrates the problem.

Sorry, function is autoClose. And t.enable is part of SimpleTimer library.

Create a new variable to hold the state of whether or not you are in autoClose mode:
uint8_t inAutoClose=0;

Then, add a line in your switch statement to set that flag when you enter that state, but not call the function if you were already in that state:
case 10:
  //automatic close
  Serial.println("A Close1");
  digitalWrite(gear1ClosePin, OFF);
  digitalWrite(gear1OpenPin, OFF);
  if (!inAutoClose) {
    inAutoClose = 1;
    t.enable(autoClose);
    autoClose();
  }
  break;

Add a line in your other switch branches to clear that flag:
case 1:
  //manually close
  inAutoClose = 0;
  [...]

If you want autoClose() to be called every 10 seconds repeatedly as the "idle" state, then you need to clear inAutoClose (set it to zero) at the end of every 10 second period. How and where you do that depends on other factors you haven't shown, like what autoClose() does, or what the timer you enable does.
Side note: avoid naming your timer name (autoClose) and your function name autoClose() the same! Does your code compile that way? It ought to throw an error.
ANSWER 2 (based on comments)
Your auto-close state is described as

Turns on for 10 seconds, after that off for 10 seconds.

This can be accomplished with a similar structure to what you have now, with a few changes. (These are my suggestions, but by no means the best or worst way.)
Edit your open and close functions:
void Open1() {
  digitalWrite(gear1OpenPin, ON);
  if (isAutoOpen) {
    t.setTimeout(10000UL, Close1); // Sets a timer to call closer in 10s
   }
}

void close1() {
  digitalWrite(gearClosePin, ON);
  if (isAutoOpen) {
    t.setTimeout(10000UL, Open1); // Sets a timer to call opener in 10s
  }
}

When you call either Open1() or Close1(), if your auto-open flag is set, then 10s later, the opposite function is called, and this keeps chaining together, every 10s.
Whenever it's time to stop this, you clear the isAutoOpen flag and disable the timers. You may wish to keep track of the timer ID that is created with the setTimeout() function, so you can disable it at any time to avoid the system going through the cycle one more time after you clear the flag.

Thank you a lot. One step closer.

If you want autoClose() to be called every 10 seconds repeatedly as the "idle" state, then you need to clear inAutoClose (set it to zero) at the end of every 10 second period.

This is little bit difficult, as all i do in that loop, changing states from HIGH to LOW.

Take a look at the setTimeout() function of SimpleTimer -- it's like the setInterval(), but is a one-shot. You can set a timeout at just under 10s and have it call a function that un-sets inAutoClose. As in t.setTimeout(9900UL, endAutoClose); where endAutoClose() is a function that just sets inAutoClose=0; You would call this setTimeout() function just before enabling the timer.

I tried that in separate simple sketch. The output was unpredictable .

In your updated example code, your switch statement switches on gearbox1, but you don't show how that value gets set to the various states. Could you update it again so that you show code that demonstrates your problem?

gearbox1 is value read from Nextion screen   gearbox1=myNextion.getComponentValue("G1");    What i am trying to achieve is, when case 10 (witch is checked once a second) run a 10 second loop turning output on and off. And the same with case 20, but different output. Tried different ways, one result is outputs changing in 1 second intervals or output blinks short on 10 second intervals. I don`t know how to post a code in comments, sorry.

Please explain "run a 10 second loop turning output on and off". The output turns on when? Stays on how long? Turns off when? "run a 10 second loop" is not clear.

Turns on for 10 seconds, after that off for 10 seconds. But i think, i have a solution, will try in couple of minutes. Could be easier than i think.


text:
Set a pin HIGH when crash occurs
I'm using an ESP8266 (NodeMCU v3). I want to set a PIN high if a soft wdt reset occurs (not expecting one). Is there a way I can do that?
Can I attach something on TX pin of the board and watch for crash dump? Maybe another Arduino?

Only after a crash? After normal reboot, the pin start LOW?

Look this link: https://www.megunolink.com/articles/how-to-detect-lockups-using-the-arduino-watchdog/

@LookAlterno that's a very useful article and program but it's pretty architecture specific. I don't think there is any way to use it with ESP8266 without an almost complete rewrite of the code.

The ESP provides a reset reason API, which lets you differentiate between a crash and a normal reset:
extern "C" {
  #include "user_interface.h"
}

const char * const RST_REASONS[] =
{
  "REASON_DEFAULT_RST",
  "REASON_WDT_RST",
  "REASON_EXCEPTION_RST",
  "REASON_SOFT_WDT_RST",
  "REASON_SOFT_RESTART",
  "REASON_DEEP_SLEEP_AWAKE",
  "REASON_EXT_SYS_RST"
};

// .. in setup():

const rst_info * resetInfo = system_get_rst_info(); //populate reset info
String diag = String(RST_REASONS[resetInfo->reason]); // turn enum index to string

if(diag == "REASON_SOFT_WDT_RST") digitalWrite(TX, HIGH);// check string, take action

The ESP8266 should  hold the pin LOW when it is active, letting it go high then signals that the program has crashed.

Can you elaborate on the matter? I  need something like that for a project.

It sounds like the idea is to drive the pin low when operating properly, but rely on the WDT-triggered reset making it a high impedance input which can be overridden by an external pullup resistor.


text:
Structure Array Initialization
I'm trying to initialize a char array which is part of a structure as follows:
#define TRUE 1
#define FALSE 0

struct s_field_def { // structure for managing display field
  char f_txt[16]; // option text
  bool f_inhibit; // set this to inhibit updating of the field on the display
};

enum field_name {F_STATE, F_PULSE};

void setup() {

  // initialize display fields structure
  struct s_field_def fields[2]; // initialize the display fields
  fields[F_STATE] =  {"HALTED", FALSE}; // displays the current run state
  fields[F_PULSE] =  {"@", TRUE}; // displays indicator of system running
}

void loop() {

}

The initialization of the structure is producing an error at these lines:
  fields[F_STATE] =  {"HALTED", FALSE}; // displays the current run state
  fields[F_PULSE] =  {"@", TRUE}; // displays indicator of system running

no match for 'operator=' (operand types are 's_field_def' and '<brace-enclosed initializer list>')

What am I doing wrong here?

As explained in Michel Keijzers' answer, you cannot use the = operator
to assign something to a string (a character array). However, you can
initialize a string using =. There is an important distinction
between assignment, which you can do anywhere in a program, an
initialization, which can only be done at the time you define a
variable.
For example:
int i = 2;  // initialization

void setup() {
    i = 4;  // assignment
}

In your specific case, you can initialize fields as follows:
struct s_field_def fields[2] = {
    {"HALTED", FALSE},  // displays the current run state
    {"@", TRUE}         // displays indicator of system running
};

That reduces code size too, both in LOC and memory. And it's clearer: declaration and initialization is just one place. Maybe you can even declare data static.

Thanks for the quick feedback about the distinction between assignment and initialization.  That makes it clear.  Problem solved!

I worked too long in an environment where this was not used. Upvoted for learning something.

You can use this (but look at the accepted answer, it shows a much neater way).
  strcpy(fields[F_STATE].f_txt, "HALTED");
  fields[F_STATE].f_inhibit = FALSE;

  strcpy(fields[F_PULSE].f_txt, "@");
  fields[F_PULSE].f_inhibit = TRUE;

I don't have a compiler so I hope it's correct.
When using C++ you can use a constructor or assignment operator, but C does not have these object oriented features.

I was hoping to avoid strcpy for the initialization.


text:
Combining code for multiple sensors (Current and Voltage Sensors) in one program
I need to operate 2 different sensors (Current and Voltage) simultaneously. I have managed to run each one of them separately and I don't know how to manipulate the code so they could work together. My background in coding is basic and I'm not the one who wrote these codes.
Here are the sketches:
1. Current Sensor Code
void setup() {

  Serial.begin(9600);
}

void loop() {

  float average = 0;
  for(int i = 0; i < 1000; i++) {
    average = average + (.0264 * analogRead(A0) -13.385) / 1000;//this is
    //for the 5A mode, if 20A or 30A mode, need to modify this formula to
    //(.19 * analogRead(A0) -25) for 20A mode and
    //(.044 * analogRead(A0) -3.78) for 30A mode
    delay(3);
  }
  Serial.println(average);
}

2. Voltage Sensor Code
/*
DC Voltmeter Using a Voltage Divider
Based on Code Created By
T.K.Hareendran
*/

int analogInput = A1;
float vout = 0.0;
float vin = 0.0;
float R1 = 30000.0; //
float R2 = 7500.0; //
int value = 0;
void setup(){
   pinMode(analogInput, INPUT);
   Serial.begin(9600);
   Serial.print("DC VOLTMETER");
}
void loop(){
   // read the value at analog input
   value = analogRead(analogInput);
   vout = (value * 5.0) / 1024.0; // see text
   vin = vout / (R2/(R1+R2));

Serial.print("INPUT V= ");
Serial.println(vin,2);
delay(500);
}

Please format your code appropriately, your question is very hard to read.

what have you tried to combine the codes? ... you did not say anything about what you expect the output to be.

How to combine two sketches.
First, make sure every global variable and function name is unique (except setup and loop). Choose the smallest sketch and rename its. variables, function names and any other named items (like DEFINE).
Is convenient to refactor things. I extract the code for reading Voltage and Current to separate functions, to reduce the count of global variable and length of each function, making things easier by reducing the side of setup() and loop().
Now, combine the code inside the setup and loop:
const int analogInput = A1;

void setup() {
  Serial.begin(9600);
  pinMode(analogInput, INPUT);
}

void loop(){
  Serial.print(getCurrent());
  Serial.print(" ");
  Serial.println(getVoltage(),2);
  delay(500);
}

float getCurrent() {
  float average = 0;
  for(int i = 0; i < 1000; i++) {
    average = average + (.0264 * analogRead(A0) -13.385) / 1000;//this is
    //for the 5A mode, if 20A or 30A mode, need to modify this formula to
    //(.19 * analogRead(A0) -25) for 20A mode and
    //(.044 * analogRead(A0) -3.78) for 30A mode
    delay(3);
  }
return average;
}

float getVoltage() {
   const float R1 = 30000.0; //
   const float R2 = 7500.0; //
   float value = analogRead(analogInput);
   float vout = (value * 5.0) / 1024.0; // see text
   float vin = vout / (R2/(R1+R2));
  return vin;
}

The bigger problem regarding combining the code is timing. You can't use delay() because the other code can't run.
You need to do let loop() run through as fast as possible and only do things when you need to i.e. when certain time elapses. And you do that with millis(), like in the Blink Without Delay example.
In your case, current reading code also needs to keep track of number of samples read and react when the sample count is reached.
const byte current_pin = A0;
const byte voltage_pin = A1;

const int max_current_sample_count = 1000;
const int current_sample_interval = 3;
const int voltage_sample_interval = 500;

// voltage divider parameters
const float R1 = 30000;
const float R2 = 7500;

// 5A current sensor parameters
const float current_sensor_scale = 0.0264;
const float current_sensor_offset = -13.385;

float current_sum = 0; // for accumulated measurements
int current_count = 0; // counter for measurements

unsigned long last_current_measure = 0; // for timing the current measurement
unsigned long last_voltage_measure = 0; // for timing the voltagemeasurement

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

void loop() {
    unsigned long time = millis();

    if (time - last_current_measure > current_sample_interval) { // if enough time elapsed to make another measurement
        last_current_measure = time; // save the time this action ran

        current_sum += current_sensor_scale * analogRead(current_pin) + current_sensor_offset;
        current_count++; // increase the counter
        if (current_count >= max_current_sample_count) { // when we reached number of samples
            // output the average and reset the sum and counter
            Serial.print("A = ");
            Serial.println(current_sum/current_count);
            current_sum = 0;
            current_count = 0;
        }
    }
    if (time - last_voltage_measure > voltage_sample_interval) { // if enough time elapsed to make another measurement
        last_voltage_measure = time; // save the time this action ran

        int value = analogRead(voltage_pin);
        float vout = (value * 5) / 1024.0;
        float vin = vout / (R2/(R1+R2));
        Serial.print("V = ");
        Serial.println(vin, 2);
    }
}

It is also a good practice that some values, that might need to be changed, are defined as constants. So you don't need to search for them inside the code which can become a problem, when you write more code. And it can prevent bugs, if you have those values in multiple places and forgot to change one.

WARNING The following advice does not generally produce compiling or working code, but is one way to start merging two separate sketches.
Without getting into the details of the code (we are not here to write code for free) I can give you the general guidelines:

put all the declarations (anything not contained in the setup or loop functions) at the top, first all from one sketch, then all from the other
copy the setup function from the first sketch and paste it after all the declarations
copy the content (anything inside the curly braces) of the setup function from the second sketch and put it inside the same function, but after all the first sketch code
rinse and repeat the last two steps for the loop functions

At this point the you might have variable name collisions and plenty of other issues, but looking at the type of code you are trying to mesh, it should work


text:
Connecting arduino ground with battery powered remote control ground
I soldered a cable to the button of a remote control and I want to simulate that button press by setting the pin to input mode and back to output (LOW) again.
For this to work I connected the ground of the battery (black wire) to the GND of the arduino.
Is this 100% safe if I hook the arduino up to the power grid or to my pc?
I also disconnected the ground pins and had my arduino connected to my pc and suddenly it worked too. I got a BSoD shortly after.

What is the voltage of the power grid?

I think the battery has like 17,5 volts.

had my arduino connected to my pc and suddenly it worked too ... what worked?

what kind of a remote control? ... you have provided almost zero information in your post.

The remote has a battery and buttons and an antenna. My goal is to be able to simulate a button click with an arduino. I also was able to simulate the button press without the two grounds connected.

All grounds should be connected to provide a common reference point.

Unless you use galvanic isolation.

Unless you use galvanic isolation (see below) then yes, you must connect the grounds together. That is vital (see here).
The main concern though is the voltage you are switching.  The Arduino cannot connect any of its IO pins directly to any voltage over 5V. Doing so will most likely damage your Arduino.
Instead, you need to use the Arduino to switch a device that will switch the button for you.  The simplest is a BJT or MOSFET:

simulate this circuit – Schematic created using CircuitLab
But there are a couple of other caveats you should consider. The most important one is to do with how far away the remote device is, and how it is powered.  Connecting the grounds of two devices that are very distant can get quite messy, since "ground" at different points may be at completely different potentials, and the voltage drop across the "ground" wire (wires don't have zero resistance) coupled with the existing ground connection through the power supplies creates a ground loop and introduces massive amounts of interference.  For this kind of arrangement, it is good to introduce ...
Galvanic Isolation
This electrically separates the two circuits completely. There is absolutely no electrical connection between your Arduino and the device you are switching.
The most common way of achieving this in low powered digital circuits is to use an opto-isolator (also called an opto-coupler).  This is basically an LED and photo-transistor together in a single package. Turn the LED on and the phototransistor turns on.  The basic arrangement is exactly the same as the circuit above, but the wire going in from the Arduino is connected to an LED:

simulate this circuit
Now you really don't care what ground potential is at the other end, nor how it is powered. As long as the opto-isolator can cope with the voltage it has to switch all will be good.  Nothing in the remote circuit can do any damage at all to the Arduino since there is no way for current to flow back from that circuit to the Arduino.

But I should not be scared that connecting the grounds and powering the arduino by pc or by dc will in any way damage the battery or do something to the power cirquit in my house?

Just connecting grounds? No. That can't hurt anything.  Connecting 17V to the Arduino's GPIO pin will kill the Arduino, but nothing else.


text:
Problem "Didn't find PN53x board" in Arduino Uno E-Card Reader
This is component to make E-Card reader, using arduino uno pn532

Code
  if (success) {
    // Display some basic information about the card
    Serial.println("Found an ISO14443A card");
    Serial.print("  UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
    Serial.print("  UID Value: ");
    nfc.PrintHex(uid, uidLength);
    Serial.println("");

    if (uidLength == 4)
    {
      // We probably have a Mifare Classic card ...
      Serial.println("Seems to be a Mifare Classic card (4 byte UID)");

      // Now we need to try to authenticate it for read/write access
      // Try with the factory default KeyA: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
      Serial.println("Trying to authenticate block 4 with default KEYA value");
      uint8_t keya[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };

      // Start with block 4 (the first block of sector 1) since sector 0
      // contains the manufacturer data and it's probably better just
      // to leave it alone unless you know what you're doing
      success = nfc.mifareclassic_AuthenticateBlock(uid, uidLength, 4, 0, keya);

      if (success)
      {
        Serial.println("Sector 1 (Blocks 4..7) has been authenticated");
        uint8_t data[16];

        // If you want to write something to block 4 to test with, uncomment
        // the following line and this text should be read back in a minute
        //memcpy(data, (const uint8_t[]){ 'a', 'd', 'a', 'f', 'r', 'u', 'i', 't', '.', 'c', 'o', 'm', 0, 0, 0, 0 }, sizeof data);
        //success = nfc.mifareclassic_WriteDataBlock (4, data);

        // Try to read the contents of block 4
        success = nfc.mifareclassic_ReadDataBlock(4, data);

        if (success)
        {
          // Data seems to have been read ... spit it out
          Serial.println("Reading Block 4:");
          nfc.PrintHexChar(data, 16);
          Serial.println("");

          // Wait a bit before reading the card again
          delay(1000);
        }
        else
        {
          Serial.println("Ooops ... unable to read the requested block.  Try another key?");
        }
      }
      else
      {
        Serial.println("Ooops ... authentication failed: Try another key?");
      }
    }

    if (uidLength == 7)
    {
      // We probably have a Mifare Ultralight card ...
      Serial.println("Seems to be a Mifare Ultralight tag (7 byte UID)");

      // Try to read the first general-purpose user page (#4)
      Serial.println("Reading page 4");
      uint8_t data[32];
      success = nfc.mifareultralight_ReadPage (4, data);
      if (success)
      {
        // Data seems to have been read ... spit it out
        nfc.PrintHexChar(data, 4);
        Serial.println("");

        // Wait a bit before reading the card again
        delay(1000);
      }
      else
      {
        Serial.println("Ooops ... unable to read the requested page!?");
      }
    }
  }
}

And i find problem, like this :

EDIT:
Now has ben change to I2C mode and detected RFID. But not detected E-Card:

How solve this is problem?

are you trying to communicate with it using SPI or I2C? You seem to have I2C connections AND half SPI

Oh, wait - you're using HSU mode? The DIP switches look like they're in HSU mode. But, you seem to have SDA connected to SCL and SCL connected to SDA if you were thinking you're using I2C - so, all in all, your wiring is completely wrong

The pictures show, a) board is in HSU (uart) mode, and b) SCL and SDA are "cross" connected - so, very useful actually :p

Now has ben change to I2C mode and detected RFID. But not detected E-Card..

Post your code, one that show the problem.

it is under sir, code..

does the code get as far as Display some basic information about the card

I'd remove the photos now - no need for photos in this question

To be blunt: We need the code before the code you posted too...

code too long, to post

if (success) {
    // Display some basic information about the card
    Serial.println("Found an ISO14443A card");
    Serial.print("  UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
    Serial.print("  UID Value: ");
    nfc.PrintHex(uid, uidLength);
    Serial.println("");
if (uidLength == 4)
{
  // We probably have a Mifare Classic card ...
  Serial.println("Seems to be a Mifare Classic card (4 byte UID)");

  // Now we need to try to authenticate it for read/write access
  // Try with the factory default KeyA: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
  Serial.println("Trying to authenticate block 4 with default KEYA value");
  uint8_t keya[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };

  // Start with block 4 (the first block of sector 1) since sector 0
  // contains the manufacturer data and it's probably better just
  // to leave it alone unless you know what you're doing
  success = nfc.mifareclassic_AuthenticateBlock(uid, uidLength, 4, 0, keya);

  if (success)
  {
    Serial.println("Sector 1 (Blocks 4..7) has been authenticated");
    uint8_t data[16];

    // If you want to write something to block 4 to test with, uncomment
    // the following line and this text should be read back in a minute
    //memcpy(data, (const uint8_t[]){ 'a', 'd', 'a', 'f', 'r', 'u', 'i', 't', '.', 'c', 'o', 'm', 0, 0, 0, 0 }, sizeof data);
    //success = nfc.mifareclassic_WriteDataBlock (4, data);

    // Try to read the contents of block 4
    success = nfc.mifareclassic_ReadDataBlock(4, data);

    if (success)
    {
      // Data seems to have been read ... spit it out
      Serial.println("Reading Block 4:");
      nfc.PrintHexChar(data, 16);
      Serial.println("");

      // Wait a bit before reading the card again
      delay(1000);
    }
    else
    {
      Serial.println("Ooops ... unable to read the requested block.  Try another key?");
    }
  }
  else
  {
    Serial.println("Ooops ... authentication failed: Try another key?");
  }
}

if (uidLength == 7)
{
  // We probably have a Mifare Ultralight card ...
  Serial.println("Seems to be a Mifare Ultralight tag (7 byte UID)");

  // Try to read the first general-purpose user page (#4)
  Serial.println("Reading page 4");
  uint8_t data[32];
  success = nfc.mifareultralight_ReadPage (4, data);
  if (success)
  {
    // Data seems to have been read ... spit it out
    nfc.PrintHexChar(data, 4);
    Serial.println("");

    // Wait a bit before reading the card again
    delay(1000);
  }
  else
  {
    Serial.println("Ooops ... unable to read the requested page!?");
  }
}

}
}

Why are you adding answers - edit your question, remove the answers

This is sir, i check using white card

Stop posting answers! Edit your answer!


text:
Using While Loop For Accurate Delays
I was trying to get the timing in between events right, (Event time is around 150ms and i need it to be accurate within +-1ms) and came upon this implementation. The actual application will not be affected by the roll over, but would like to see if any of you guys (experts) can point out any flaws in using an empty while loop for time events, besides slightly higher power consumption.
This implementation gave me very accurate time spacings:
unsigned long previousMillis = millis();
Serial.print("ONE: ");
Serial.println(millis());
while(millis() - previousMillis < 1000);
Serial.print("SECOND: ");
Serial.println(millis());

compared with...
Serial.print("ONE: ");
Serial.println(millis());
delay(1000);
Serial.print("SECOND: ");
Serial.println(millis());

Which yields some errors after every step.

±1 ms accuracy is borderline for millis(). Use micros() instead.

Thanks for pointing that out. I added that my event time is actually around 150 ms. The micros() function is stated in the documentation to be accurate up to 16000us/16ms only. But does not state how much is the drift. Might need to test it out..

Have you looked at the source code for delay()? What makes you think your while loop would use more power than the while loop in the delay() function?

“The micros() function is stated in the documentation to be accurate up to 16000us/16ms only.” That's incorrect. In what documentation did you find that? micros() can be used to measure times up to 71.6 minutes, which is its rollover period. The drift of micros() is the drift of the ceramic oscillator clocking your MCU. Typically less than 0.5%. Any timing method (delay(), millis(), micros(), hardware timers, etc...) will suffer the same drift, unless using an external time source, like an RTC.

@EdgarBonet "In what documentation did you find that?" The official delayMicroseconds reference page: https://www.arduino.cc/reference/en/language/functions/time/delaymicroseconds/

If you want to be sure of the time between event, you need to use interrupt timer. In all other cases, even a small change in your code will affect the time needed for the loop to execute, and will change the delay between event.

delayMicroseconds does not use micros() which is what was suggested. micros() has a granularity of 4 µs. However delayMicroseconds can be used inside an ISR as it does not rely upon interrupts, whereas micros() does (need interrupts - eventually).

See the documentation for micros

There are many options for executing a task periodically. The most
straightforward is to use a slight variation of code given in the Blink
Without Delay[] Arduino tutorial:
const uint32_t PERIOD = 150000;  // 150 ms

void loop() {
    static uint32_t last_time;
    if (micros() - last_time >= PERIOD) {
        last_time += period;
        do_periodic_task();
    }
    do_other_tasks();
}

Note two changes relative to the code in the tutorial:

This is using micros() instead of millis(). This way the timing
resolution is 4 µs instead of 1 to 2 milliseconds.
last_time is updated as last_time += period instead of
last_time = micros(). This way, even if the periodic task got
delayed by the other tasks, these delays don't add up.

The timing will not be perfect: you will have both drift and jitter.
The drift comes from the inaccuracy of the ceramic resonator clocking
the microcontroller. These resonators have typically 0.5% frequency
tolerance, although the typical frequency error is more likely to be
around ±0.1% (i.e. 0.15 ms error in a 150 ms period). Note
that a poorly written code would add it's own drift, e.g. if you do
last_time = micros(), but this does not.
The jitter comes from the fact that the clock is checked only once per
loop iteration, and your periodic task can then be delayed by the other
tasks. The amplitude of the jitter is the maximum time taken by a loop
iteration.
Despite these imperfections, this would be my first choice unless I
really needed better timing accuracy.
If you need lower drift, one option is to calibrate your Arduino clock.
You measure how fast or slow it is, and you tweak the PERIOD constant
accordingly. For example, if you measure the clock to be 700 ppm
slow, you would fix it like this:
const uint32_t NOMINAL_PERIOD = 150000;  // 150 ms

// Adjust the period to account for clock drift.
const float FREQUENCY_OFFSET = -700e-6;  // -700 ppm
const uint32_t PERIOD = NOMINAL_PERIOD * (1 + FREQUENCY_OFFSET);

This technique allows you to tune the frequency with about 6.7 ppm
resolution, for a period of 150 ms. You cannot reasonably expect
anything better, as the frequency of the ceramic resonator is not very
stable anyway.
If you need lower jitter, one option is to perform a blocking wait:
you ask the processor to do nothing but wait until it's time to perform
the periodic task. This is similar to the code you posted in your
question:
void loop() {
    static uint32_t last_time;
    while (micros() - last_time < PERIOD) ;  // busy wait
    last_time += period;
    do_periodic_task();
}

This will not completely suppress the jitter, but it will reduce it to
just the time taken by the while loop. However, there is a big issue
with this way of coding: now your processor does nothing but the
periodic task. It may not be a problem right now, but as your project
grows, it is more than likely that at some point you will want to handle
extra tasks like, e.g. responding to some user input.
If you want to avoid completely blocking the processor on the busy wait,
yet you want the smallest possible jitter, you could try some sort of
compromise: you let the processor take care of other tasks until it is
almost time to perform the periodic task. Then you switch to the
blocking mode where the processor does nothing but wait for the clock.
Here, “almost time” would be defined by the maximum time your loop can
take:
const uint32_t MAX_LOOP_TIME = 2000;  // assume 2 ms

void loop() {
    static uint32_t last_time;
    if (micros() - last_time >= PERIOD - MAX_LOOP_TIME) {
        while (micros() - last_time < PERIOD) ;  // busy wait
        last_time += period;
        do_periodic_task();
    }
    do_other_tasks();
}

Another option, that has been mentioned in comments, is to trigger the
task by a timer. This will work if it is a very short task that can
safely be run with interrupts disabled. You have four 16-bit timers on
your Mega, so you can presumably spare one for timing this task. This
could be done with Timer 1 as follows (warning: untested code):
const int TIMER_PRESCALER = 64;
const float F_TIMER = F_CPU / TIMER_PRESCALER;
const float PERIOD = 150e-3;
const uint16_t TIMER_PERIOD = F_TIMER*PERIOD + 0.5;  // round to nearest

void setup() {
    TCCR1B = 0;            // stop the timer
    OCR1A  = TIMER_PERIOD - 1;
    TIFR1 |= _BV(OCF1A);   // clear TIMER1_COMPA interrupt flag
    TIMSK1 = _BV(OCIE1A);  // enable TIMER1_COMPA interrupt
    TCCR1A = 0;            // no PWM
    TCCR1B = _BV(WGM12)    // CTC mode, TOP = OCR1A
           | _BV(CS10)     // clock at F_CPU / 64
           | _BV(CS11);    // ditto
}

ISR(TIMER1_COMPA) {
    do_periodic_task();
}

Note that TIMER_PERIOD will be 37500. If you want to tune it to
account for an inaccurate clock frequency, your tuning resolution will
be about 26.7 ppm.
The interrupt technique should get you sub-microsecond jitter most of
the time. However, every now and then the Timer 0 interrupt (the
one responsible for updating the millis() counter) will delay your
interrupts for a few microseconds. Beware also that some libraries can
delay interrupts for excessive amounts of time. Software Serial is an
infamous offender.

Those two are not the same "program". The first one start counting before Serial.print. The other first print and then delay for a second.
We have two piece of code:

The first take 1000ms to reach "SECOND" (plus some overhead).
The second take 1000ms + time needed for two Serial.prints and a millis() call to reach "SECOND" (plus the same overhead).

The first approach is better, because you start counting before doing operations of undetermined length. So, it's immune to any factor affecting running time, like time spent in interrupts. And you don't need to retune it if you change the sketch.

That's interesting, I didn't notice that! The Serial.print is just for checking. I will implement Port Manipulation with this method so the accuracy should be sufficient. Just want to see if using the while loop like this might cause some issues unknown to my skill level.

@JamesLow. There  are some fine points. If delay is too big, the watchdog could reset the board. And on a ESP8266 based system, you have to call yield inside the do-while to let processor manage Wi-Fi.

For better accuracy, you should not be "delaying until it's time to do something", but instead "checking if it's time to do it yet".
It's all very well saying you want something to happen every 150ms and delaying between actions for 150ms, but that won't yield you an event that happens every 150ms - it yields you an event that takes X amount of time with a delay of Y between each event, resulting in an overall period of X+Y, which is not what you want.
I cover the proper ways to deal with timing of regular events in this existing answer:

delay(time); vs if(millis()-previous>time); and drift


text:
Looking for SPI documentation
I'm trying to use an Arduino as a slave and was searching for examples which I found many. But apart from the examples, I haven't found any documentation explaining many thing that show up in those examples.
For example, I'd like a document that would state what things like the following are:
-SPCR
-SPE
-SPDR
-ISR
-SPI_STC_vect
I'm asking this, because I don't and can't just copy an example and hope that it'll work, I really need to know what I'm doing.
Thank you,
João

you know, there is a SPI library?

Yes, I do know there's a library. But is there any document available that says what are the resources of that library?

reference of he SPI library https://www.arduino.cc/en/Reference/SPI

Atmega datasheet http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Datasheet.pdf

Thank you very much, I'll look into the Atmega datasheet, didn't occur to me looking into it.

You are confusing SPI, a de facto standard, with the Arduino/Atmel hardware support for SPI.
SPCR, SPE and SPDR are registers of the Atmel MCU, part of the hardware support.
ISR is Interrupt Service Routine and SPI_STC_vect is the vector that point to that code. That is where the data received from the cable is read finally.

Take a look at Nick Gammon's SPI explanations also. Very good, with timing explained as well.
http://www.gammon.com.au/spi

His work is amazing, unfortunately he doesn't explain what those things are, apart from ISR and SPDR. And I had no idea from where the other things came. But there are already good answers that give me somewhere to look into.
Thank you very much!

I also explain SPI right here on this site: https://arduino.stackexchange.com/questions/16348/how-do-you-use-spi-on-an-arduino/  - As for the register names, they are explained in the datasheet.

Whilst I have a personal interest in the answer, it simply isn't practical to include or even summarize a lengthy post like an explanation of how SPI works. The OP is asking for documentation and this answer is giving a link to it. In my comment above I point out that there is more documentation available on this site which means it is less likely to go link-dead. Another answer might be to reference the datasheet, which again would have to be link-only, unless maybe you quoted a couple of pages.