0

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.

wired

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 – Juraj Feb 5 '18 at 6:23
  • how are you getting 5v on the lolin board? (not from VIN). – dandavis Feb 6 '18 at 0:24
  • 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. – GERMAN Feb 6 '18 at 1:15
  • 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. – GERMAN Feb 6 '18 at 1:19
  • is the ground of lolin connected with ground of Nano? – Juraj Feb 8 '18 at 5:34
0

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. – GERMAN Feb 8 '18 at 17:12
  • 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. – GERMAN Feb 12 '18 at 4:52
  • HI @sundaysfantasy, I just put a 4N35 and it is working – GERMAN Feb 12 '18 at 22:08
  • Good to know it works with an optocoupler too. – sundaysfantasy Feb 14 '18 at 12:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.