Problem with SPI comms using NodeMCU ver 3, Nano and SD
Posted: Thu Feb 08, 2018 2:21 am
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.
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
Here is my code for Nano as SPI Slave
the problem
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.
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