SD card on ESP32 with radiohead
I was trying to work out the sd card on heltec lora board together with lora and GPS.
The device need to:
1. get geo info from GPS.
2. Send out through lora.
3. record in sd card.
I have done the 1 and 2, but blocked on 3. since sd and lora both use spi interface.
I was not so familiar with SPI interface, nor how sw lib was written. It took me a while to make sd card read write works on heltec board.
https://ldsrc.blogspot.tw/2018/02/micro-sd-card-for-esp32.html
Now, how to make both work?
I think I have solved the questions on pins:
SPI SCK MISO MOSI CS
Lora 05 19 27 18 (with reset at 14)
SD 05 19 27 21
when I tested SD, I pull up 18 to high, to make lora unselected, so that they stay tri state on MISO....this works both on hard wired, or using digital write.
I start to search on how to make 2 spi devices works together on a same bus.
Here is a very good example here:
https://www.circuitsathome.com/mcu/running-multiple-slave-devices-on-arduino-spi-bus/
To understand a little bit on SPI, there is a clock line from master, which is idle if not used, and CS is normally high, and write low by master to signal device to work. when CS is high, the device "should keep on tri-state", which means it does not influence other lines.
So need to find out how to arrange CS, not sure if each lib arrange correctly.
But according to toturial, you need to declair it as out put.
Beside the CS, there are some parameters in SPI spec.
good tutorial here:http://tronixstuff.com/2011/05/13/tutorial-arduino-and-the-spi-bus/
1. Frequency
2. Bit order
3. mode
So, have to check the above 3 items used in radiohead lib and sd lib.
I'm not so familiar with C lib, and the radio head lib seems to be more complicated.
In the Arduino_projects\hardware\espressif\esp32\libraries\SD\src\SD.h
there is:
bool begin(uint8_t ssPin=SS, SPIClass &spi=SPI, uint32_t frequency=4000000, const char * mountpoint="/sd");
which indicate me that the frequency of sd lib is 4M
RadioHead:
from RH_RF95.cpp:
RH_RF95::RH_RF95(uint8_t slaveSelectPin, uint8_t interruptPin, RHGenericSPI& spi)
did not see any varable to assign frequency, but did found a default value in RHHardwareSPI.cpp the default seems to be 1000000
it seems to have default value at: MODE0 and MSBFIRST
_spi = spiStartBus(_spi_num, _div, SPI_MODE0, SPI_MSBFIRST);
if(!_spi) {
return;
}
From RH_RF95_h I found it include <RHSPIDriver.h>
then it include
#include <RHGenericDriver.h>
#include <RHHardwareSPI.h>
In the RHHardwareSPI.cpp there are several platform dependant setting about setDataMode, setBitOrder, setFrequency, but I could not find ESp32, only esp8266
which has defaut case in swith option:
default:
SPI.setDataMode ( SPI_MODE0 );
// bitorder
SPI.setBitOrder(_bitOrder == BitOrderLSBFirst ? LSBFIRST : MSBFIRST);
default:
SPI.setFrequency(1000000);
So, combine the above infomation, it seems that only the frequency is different, and sd lib can adjust frequency to 1000000, it seems that keep RH lib and modi(or not the sd lib could be a solution)
I took the example of radiohead RF95 client example and add/modi as following:
Init of both devices return OK,and lora sending seems ok. But I did not get any data on the receiver side.
summary:
I write lora chip select to high and inited the sd card, it returns ok, and then set lora frequency and sending. not thing report failed, but I did not get any thing on the receiver side.
update: It turns out that I change the frequency in a stupid way. the tutorial of adfruit use 915.0, and I set to 433E6, the lib does not reply with error, but seems wrong on setting frequency. Maybe I should try 433.0
After understanding this mistake from my part, I decided to fist use the default frequency for testing which is 434.0
with SD card inited, the sending and receiving are both correct.
Then I play with the SD_test functions, this lib provide several functions:
// createDir(SD, "/mydir");
// listDir(SD, "/", 0);
// removeDir(SD, "/mydir");
// listDir(SD, "/", 2);
// writeFile(SD, "/test.txt", "12345");
// writeFile(SD, "/test.txt", "02");
// appendFile(SD, "/test.txt", "World!\n");
// readFile(SD, "/hello.txt");
// deleteFile(SD, "/test.txt");
// renameFile(SD, "/hello.txt", "/foo.txt");
readFile(SD, "/test.txt");
listDir(SD, "/", 0);
// testFileIO(SD, "/test.txt");
if I use write.File, it will clear the file and write your string, and this lastest one is the one to stay on card.
So, for a series of logging, it would be right to use append. if the file name does not exist the first time, it create for you.
The I managed to make a demo on sending data through lora then log into sd card.(rf95_client_esp32_SD_3.ino)
The device need to:
1. get geo info from GPS.
2. Send out through lora.
3. record in sd card.
I have done the 1 and 2, but blocked on 3. since sd and lora both use spi interface.
I was not so familiar with SPI interface, nor how sw lib was written. It took me a while to make sd card read write works on heltec board.
https://ldsrc.blogspot.tw/2018/02/micro-sd-card-for-esp32.html
Now, how to make both work?
I think I have solved the questions on pins:
SPI SCK MISO MOSI CS
Lora 05 19 27 18 (with reset at 14)
SD 05 19 27 21
when I tested SD, I pull up 18 to high, to make lora unselected, so that they stay tri state on MISO....this works both on hard wired, or using digital write.
I start to search on how to make 2 spi devices works together on a same bus.
Here is a very good example here:
https://www.circuitsathome.com/mcu/running-multiple-slave-devices-on-arduino-spi-bus/
To understand a little bit on SPI, there is a clock line from master, which is idle if not used, and CS is normally high, and write low by master to signal device to work. when CS is high, the device "should keep on tri-state", which means it does not influence other lines.
So need to find out how to arrange CS, not sure if each lib arrange correctly.
But according to toturial, you need to declair it as out put.
Beside the CS, there are some parameters in SPI spec.
good tutorial here:http://tronixstuff.com/2011/05/13/tutorial-arduino-and-the-spi-bus/
1. Frequency
2. Bit order
3. mode
So, have to check the above 3 items used in radiohead lib and sd lib.
I'm not so familiar with C lib, and the radio head lib seems to be more complicated.
Frequency:
SD part:In the Arduino_projects\hardware\espressif\esp32\libraries\SD\src\SD.h
there is:
bool begin(uint8_t ssPin=SS, SPIClass &spi=SPI, uint32_t frequency=4000000, const char * mountpoint="/sd");
which indicate me that the frequency of sd lib is 4M
RadioHead:
from RH_RF95.cpp:
RH_RF95::RH_RF95(uint8_t slaveSelectPin, uint8_t interruptPin, RHGenericSPI& spi)
did not see any varable to assign frequency, but did found a default value in RHHardwareSPI.cpp the default seems to be 1000000
Bit order and mode:
I did not found any in SD lib, but in the esp32\libraries\spi\scr\SPI.cppit seems to have default value at: MODE0 and MSBFIRST
_spi = spiStartBus(_spi_num, _div, SPI_MODE0, SPI_MSBFIRST);
if(!_spi) {
return;
}
From RH_RF95_h I found it include <RHSPIDriver.h>
then it include
#include <RHGenericDriver.h>
#include <RHHardwareSPI.h>
In the RHHardwareSPI.cpp there are several platform dependant setting about setDataMode, setBitOrder, setFrequency, but I could not find ESp32, only esp8266
which has defaut case in swith option:
default:
SPI.setDataMode ( SPI_MODE0 );
// bitorder
SPI.setBitOrder(_bitOrder == BitOrderLSBFirst ? LSBFIRST : MSBFIRST);
default:
SPI.setFrequency(1000000);
So, combine the above infomation, it seems that only the frequency is different, and sd lib can adjust frequency to 1000000, it seems that keep RH lib and modi(or not the sd lib could be a solution)
I took the example of radiohead RF95 client example and add/modi as following:
#include <SPI.h>
#include <RH_RF95.h>#include "FS.h"#include "SD.h"#define RFM95_CS 18 //#define RFM95_RST 14#define RFM95_INT 26// Change to 434.0 or other frequency, must match RX's freq!#define RF95_FREQ 433E6 //915.0// Singleton instance of the radio driverRH_RF95 rf95(RFM95_CS, RFM95_INT);void setup(){Serial.begin(115200);delay(100);// manual resetdigitalWrite(RFM95_RST, LOW);delay(10);digitalWrite(RFM95_RST, HIGH);delay(10);while (!rf95.init()) {Serial.println("LoRa radio init failed");while (1);}Serial.println("LoRa radio init OK!");pinMode(RFM95_CS, OUTPUT);digitalWrite(RFM95_CS, HIGH);if (SD.begin(21,SPI,1000000)) { //spi on heltec lora oled, with 21 for sd cs,Serial.println("SD initialization OK");}else{Serial.println("SD initialization failed");}// Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbMif (!rf95.setFrequency(RF95_FREQ)) {Serial.println("setFrequency failed");while (1);}Serial.print("Set Freq to: "); Serial.println(RF95_FREQ);// Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on// The default transmitter power is 13dBm, using PA_BOOST.// If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then// you can set transmitter powers from 5 to 23 dBm:rf95.setTxPower(23, false);Serial.println("Sending to rf95_server");}int16_t packetnum = 0; // packet counter, we increment per xmissionvoid loop(){// Send a message to rf95_serverchar radiopacket[20] = "Hello World # ";itoa(packetnum++, radiopacket+13, 10); // convert int to stringSerial.print("Sending "); Serial.println(radiopacket);radiopacket[19] = 0;Serial.println("Sending..."); delay(10);rf95.send((uint8_t *)radiopacket, 20);Serial.println("Waiting for packet to complete..."); delay(10);rf95.waitPacketSent();Serial.println("packet Sent");/*// Now wait for a replyuint8_t buf[RH_RF95_MAX_MESSAGE_LEN];uint8_t len = sizeof(buf);Serial.println("Waiting for reply..."); delay(10);if (rf95.waitAvailableTimeout(1000)){// Should be a reply message for us nowif (rf95.recv(buf, &len)){Serial.print("Got reply: ");Serial.println((char*)buf);Serial.print("RSSI: ");Serial.println(rf95.lastRssi(), DEC);}else{Serial.println("Receive failed");}}else{Serial.println("No reply, is there a listener around?");}*/// sd_logging();delay(1000);while(packetnum > 10){ }//}
Init of both devices return OK,and lora sending seems ok. But I did not get any data on the receiver side.
summary:
I write lora chip select to high and inited the sd card, it returns ok, and then set lora frequency and sending. not thing report failed, but I did not get any thing on the receiver side.
update: It turns out that I change the frequency in a stupid way. the tutorial of adfruit use 915.0, and I set to 433E6, the lib does not reply with error, but seems wrong on setting frequency. Maybe I should try 433.0
After understanding this mistake from my part, I decided to fist use the default frequency for testing which is 434.0
with SD card inited, the sending and receiving are both correct.
Then I play with the SD_test functions, this lib provide several functions:
// createDir(SD, "/mydir");
// listDir(SD, "/", 0);
// removeDir(SD, "/mydir");
// listDir(SD, "/", 2);
// writeFile(SD, "/test.txt", "12345");
// writeFile(SD, "/test.txt", "02");
// appendFile(SD, "/test.txt", "World!\n");
// readFile(SD, "/hello.txt");
// deleteFile(SD, "/test.txt");
// renameFile(SD, "/hello.txt", "/foo.txt");
readFile(SD, "/test.txt");
listDir(SD, "/", 0);
// testFileIO(SD, "/test.txt");
if I use write.File, it will clear the file and write your string, and this lastest one is the one to stay on card.
So, for a series of logging, it would be right to use append. if the file name does not exist the first time, it create for you.
The I managed to make a demo on sending data through lora then log into sd card.(rf95_client_esp32_SD_3.ino)
留言
張貼留言