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|