So you're a Noob? Post your questions here until you graduate! Don't be shy.

User avatar
By German_Ramirez
#73793 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.

Image

the ground cable between Esp12e and Nano is not showed in the picture to check if that will be the problem.

Here is my code for ESP12e as SPI Master

Code: Select all/*Master - ESP12e create a variable string to be sent to slave - Nano
    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);
}


Here is my code for Nano as SPI Slave

Code: Select all/* 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;
  }
}


the problem
Image