Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
meteorolog
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
5
Issues
5
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
EMM
meteorolog
Commits
637df50d
Commit
637df50d
authored
Aug 19, 2017
by
Nelso Jost
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
FIX refactor meteorolog base code to eliminate delay()
parent
a7ed9d7e
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
478 additions
and
197 deletions
+478
-197
Makefile
arduino/Makefile
+2
-2
meteorolog.ino
arduino/meteorolog/meteorolog.ino
+3
-2
esplogger.ino
nodemcu/esplogger/esplogger.ino
+19
-151
meteorologger.cpp
nodemcu/esplogger/meteorologger.cpp
+141
-0
meteorologger.h
nodemcu/esplogger/meteorologger.h
+69
-0
repl_meteorologger.h
nodemcu/esplogger/repl_meteorologger.h
+35
-0
repl_sdcard.cpp
nodemcu/esplogger/repl_sdcard.cpp
+19
-1
repl_sdcard.h
nodemcu/esplogger/repl_sdcard.h
+22
-2
sdcard.cpp
nodemcu/esplogger/sdcard.cpp
+137
-38
sdcard.h
nodemcu/esplogger/sdcard.h
+7
-1
pushbutton.cpp
nodemcu/pushbutton.cpp
+24
-0
No files found.
arduino/Makefile
View file @
637df50d
...
...
@@ -2,8 +2,8 @@ include ../utils/platformio/Makefile
INOPROJECT
=
meteorolog
BAUD
=
1152
00
BOARD
=
uno
BAUD
=
96
00
BOARD
=
nanoatmega328
monitor
:
qtmonitor
#
arduino/meteorolog/meteorolog.ino
View file @
637df50d
...
...
@@ -8,7 +8,7 @@
#include "mysensors.h"
#include "boardcommands.h"
#define BAUDRATE
1152
00
#define BAUDRATE
96
00
String
stream_line
;
...
...
@@ -25,6 +25,7 @@ void loop()
if
(
Serial
.
available
())
{
stream_line
=
Serial
.
readString
();
Serial
.
println
(
execute_board_command
(
stream_line
.
trim
()));
//stream_line.trim();
Serial
.
println
(
execute_board_command
(
stream_line
));
}
}
nodemcu/esplogger/esplogger.ino
View file @
637df50d
...
...
@@ -4,46 +4,27 @@
* Purpose: Entry point for the Arduino Toolchain.
*---------------------------------------------------------------------------*/
#include <Arduino.h>
#include <Ticker.h>
#include <SPI.h>
#include <SD.h>
#include <SoftwareSerial.h>
#include "nodemcu_pinout.h"
#include "repl.h"
#include "repl_gpio.h"
#include "repl_sdcard.h"
#include "repl_wifi.h"
#include "repl_meteorologger.h"
#define BAUDRATE 115200
#define DATALOG_FILENAME "datalog.txt"
#define PIN_LED D3
#define PIN_BUTTON D0
#define ARDUINO_TX D1 // (soft RX)
#define ARDUINO_RX D2 // (soft TX)
#define ARDUINO_BAUDRATE 115200
const
int
chipSelect
=
4
;
void
REPL_ARDUINO
(
REPL
*
repl
);
void
REPL_METEOROLOG
(
REPL
*
repl
);
#include "nodemcu_pinout.h"
#include "meteorologger.h"
#define BAUDRATE 115200
#define DATALOG_FILENAME "datalog.txt"
typedef
struct
{
REPL
*
repl
;
float
interval
;
String
command
;
String
board_hash
;
}
METEOROLOG_args
;
#define ARDUINO_TX D1 // (soft RX)
#define ARDUINO_RX D2 // (soft TX)
#define ARDUINO_BAUDRATE 9600
#define CS_PIN D8
void
meteorolog_callback
(
METEOROLOG_args
*
args
);
void
sd_datalog
(
String
datalog
,
REPL
*
repl
);
void
server_datalog
(
String
datalog
,
REPL
*
repl
);
#define PIN_NOTIFY_ACTIVE D4
REPL_COMMAND
commands
[]
=
\
...
...
@@ -51,158 +32,45 @@ REPL_COMMAND commands[] =\
ALLCMD_REPL_GPIO
,
ALLCMD_REPL_SDCARD
,
ALLCMD_REPL_WIFI
,
{
"arduino"
,
REPL_ARDUINO
,
"arduino <command>"
,
"Send command to Arduino via software serial."
},
{
"meteorolog"
,
REPL_METEOROLOG
,
"meteorolog <interval_secs> <arduino_command>"
,
"Activate meterolog timer on given interval (seconds)."
},
ALLCMD_REPL_METEOROLOGGER
,
{
NULL
}
};
REPL
repl
(
commands
);
int
led_state
=
0
;
int
button_state
=
0
;
SoftwareSerial
arduinoSerial
(
ARDUINO_TX
,
ARDUINO_RX
);
// RX, TX
Ticker
timer_button
;
Ticker
timer_meteorolog
;
Meteorologger
meteorologger
(
&
arduinoSerial
,
&
repl
,
String
(
DATALOG_FILENAME
));
SoftwareSerial
arduinoSerial
(
ARDUINO_TX
,
ARDUINO_RX
);
// RX, TX
void
setup
()
{
Serial
.
begin
(
BAUDRATE
);
arduinoSerial
.
begin
(
ARDUINO_BAUDRATE
);
if
(
!
SD
.
begin
(
chipSelect
))
{
repl
.
log
(
"
\n
[ERROR] Unable to initialize SD card."
);
}
// pinMode(PIN_BUTTON, INPUT);
// timer_button.attach(0.1, toggle_led);
sdcard_begin
(
CS_PIN
);
}
void
loop
()
{
repl
.
update
();
}
void
toggle_led
()
{
int
reading
=
digitalRead
(
PIN_BUTTON
);
if
(
button_state
!=
reading
)
{
button_state
=
reading
;
if
(
button_state
==
HIGH
)
{
led_state
=
!
led_state
;
pinMode
(
PIN_LED
,
OUTPUT
);
digitalWrite
(
PIN_LED
,
led_state
);
}
}
meteorologger
.
update
();
}
void
REPL_ARDUINO
(
REPL
*
repl
)
{
Serial
.
println
();
arduinoSerial
.
print
(
repl
->
get_arg
(
1
));
delay
(
1500
);
while
(
arduinoSerial
.
available
())
{
Serial
.
write
(
arduinoSerial
.
read
());
}
meteorologger
.
sendCommand
(
repl
->
get_arg
(
1
));
}
void
REPL_METEOROLOG
(
REPL
*
repl
)
{
METEOROLOG_args
*
args
=
new
METEOROLOG_args
;
args
->
interval
=
repl
->
get_arg
(
1
).
toFloat
();
args
->
command
=
repl
->
get_arg
(
2
);
args
->
board_hash
=
repl
->
get_arg
(
3
);
args
->
repl
=
repl
;
if
(
args
->
interval
==
0
)
{
timer_meteorolog
.
detach
();
repl
->
log
(
"
\n
[INFO] Deactivated meteorolog timer."
);
}
else
{
timer_meteorolog
.
attach
(
args
->
interval
,
meteorolog_callback
,
args
);
repl
->
log
(
"
\n
[INFO] Activated meteorolog timer with "
+
String
(
args
->
interval
)
+
" s interval."
);
meteorolog_callback
(
args
);
}
meteorologger
.
activate
(
repl
->
get_arg
(
1
).
toFloat
(),
repl
->
get_arg
(
2
));
}
void
meteorolog_callback
(
METEOROLOG_args
*
args
)
void
REPL_TAILDATALOG
(
REPL
*
repl
)
{
args
->
repl
->
log
(
"
\n
[INFO] Performing datalog.."
);
Serial
.
println
();
arduinoSerial
.
print
(
args
->
command
);
args
->
repl
->
log
(
"
\n
[INFO] Sent command '"
+
args
->
command
+
"' to arduino."
);
delay
(
1500
);
String
response
=
""
;
while
(
arduinoSerial
.
available
())
{
response
+=
arduinoSerial
.
read
();
}
response
.
trim
();
args
->
repl
->
log
(
"
\n
[INFO] Got response: '"
+
response
+
"'"
);
if
(
response
.
length
()
>
0
)
{
sd_datalog
(
response
,
args
->
repl
);
// server_datalog(response, args->repl);
}
else
{
args
->
repl
->
log
(
"
\n
[ERROR] Empty datalog response"
);
}
sdcard_tail
(
meteorologger
.
datalog_filename
);
}
void
sd_datalog
(
String
datalog
,
REPL
*
repl
)
{
Sd2Card
sd_card
;
SdVolume
sd_volume
;
if
(
!
sd_card
.
init
(
SPI_HALF_SPEED
,
chipSelect
))
{
repl
->
log
(
"
\n
[ERROR] Unable to detect/init SD card."
);
return
;
}
if
(
!
sd_volume
.
init
(
sd_card
))
{
repl
->
log
(
"
\n
[ERROR] SD card is plugged but no volume was found."
);
return
;
}
File
sd_file
=
SD
.
open
(
DATALOG_FILENAME
,
FILE_WRITE
);
if
(
!
sd_file
)
{
repl
->
log
(
"
\n
[ERROR] Unable to open '"
+
String
(
DATALOG_FILENAME
)
+
"'"
);
return
;
}
int
written
=
sd_file
.
println
(
datalog
);
sd_file
.
close
();
repl
->
log
(
"
\n
[INFO] "
+
String
(
written
)
+
" bytes written at '"
+
String
(
DATALOG_FILENAME
)
+
"'"
);
}
void
server_datalog
(
String
datalog
,
REPL
*
repl
)
{
String
response
=
String
(
"POST emm/api/post/rawsensordata HTTP/1.1
\r\n
"
)
+
\
"Host: dados.cta.if.ufrgs.br"
+
\
"Content-type: Application/JSON"
;
// TODO: IMPLEMENT HTML CLIENT REST API
}
nodemcu/esplogger/meteorologger.cpp
0 → 100644
View file @
637df50d
#include <Arduino.h>
#include <SoftwareSerial.h>
#include "meteorologger.h"
#include "repl.h"
#include "sdcard.h"
Meteorologger
::
Meteorologger
(
SoftwareSerial
*
arduinoSerial
,
REPL
*
repl
,
String
datalog_filename
)
{
this
->
arduinoSerial
=
arduinoSerial
;
this
->
repl
=
repl
;
this
->
datalog_filename
=
datalog_filename
;
pinMode
(
this
->
pin_notify
,
OUTPUT
);
}
void
Meteorologger
::
update
(
void
)
{
if
(
!
this
->
arduinoSerial
->
available
())
return
;
this
->
repl
->
log
(
"
\n
[DEBUG] Reading arduino serial response.."
);
this
->
response
=
this
->
arduinoSerial
->
readString
();
this
->
response
.
trim
();
this
->
repl
->
log
(
"
\n
[INFO] Recieved: '"
+
this
->
response
+
"' ("
+
String
(
this
->
response
.
length
())
+
" bytes)"
);
if
(
this
->
interval
==
0
)
return
;
if
(
!
sdcard_write
(
this
->
datalog_filename
,
this
->
response
+
"
\n
"
))
{
this
->
status_level
=
STATUS_LEVEL_ERROR_SD
;
return
;
}
this
->
status_level
=
STATUS_LEVEL_OK
;
}
void
Meteorologger
::
activate
(
float
interval
,
String
command
)
{
this
->
interval
=
interval
;
if
(
interval
==
0
)
{
this
->
ticker_meteorolog
.
detach
();
this
->
ticker_notify_status
.
detach
();
this
->
repl
->
log
(
"
\n
[INFO] Deactivated meteorolog timer."
);
digitalWrite
(
this
->
pin_notify
,
1
);
}
else
{
this
->
command
=
command
;
this
->
ticker_meteorolog
.
attach
(
interval
*
60
,
this
->
meteorolog_callback
,
this
);
this
->
notify_on
();
this
->
repl
->
log
(
"
\n
[INFO] Activated meteorolog timer with "
+
String
(
interval
)
+
" min ("
+
String
(
interval
*
60
)
+
" sec) interval."
);
sdcard_write
(
this
->
datalog_filename
,
"# --- [START] --- command='"
+
command
+
"' --- interval_mins="
+
String
(
interval
)
+
"
\n
"
);
this
->
sendCommand
(
command
);
}
}
void
Meteorologger
::
sendCommand
(
String
command
)
{
this
->
response
=
""
;
this
->
command
=
command
;
this
->
repl
->
log
(
"
\n
[DEBUG] Sending command '"
+
this
->
command
+
"' to arduino."
);
this
->
arduinoSerial
->
print
(
this
->
command
);
this
->
ticker_arduino_threshold
.
attach
(
this
->
arduino_threshold
,
this
->
arduino_threshold_callback
,
this
);
}
void
Meteorologger
::
meteorolog_callback
(
Meteorologger
*
m
)
{
m
->
sendCommand
(
m
->
command
);
}
void
Meteorologger
::
arduino_threshold_callback
(
Meteorologger
*
m
)
{
if
(
m
->
response
==
""
)
{
m
->
repl
->
log
(
"
\n
[ERROR] "
+
String
(
m
->
arduino_threshold
)
+
" secs "
"without Arduino SWSerial response."
);
if
(
m
->
interval
>
0
)
{
m
->
status_level
=
STATUS_LEVEL_ERROR_SWSER
;
}
}
m
->
ticker_arduino_threshold
.
detach
();
}
void
Meteorologger
::
notify_status_callback
(
Meteorologger
*
m
)
{
m
->
blink_count
=
m
->
status_level
*
2
-
1
;
m
->
ticker_blink_status
.
attach
(
m
->
blink_interval
,
m
->
blink_status_callback
,
m
);
m
->
notify_off
();
}
void
Meteorologger
::
blink_status_callback
(
Meteorologger
*
m
)
{
m
->
pin_notify_state
=
!
m
->
pin_notify_state
;
digitalWrite
(
m
->
pin_notify
,
m
->
pin_notify_state
);
if
(
m
->
blink_count
>
0
)
{
m
->
blink_count
-=
1
;
}
else
{
m
->
ticker_blink_status
.
detach
();
m
->
notify_on
();
}
}
void
Meteorologger
::
notify_on
(
void
)
{
this
->
pin_notify_state
=
this
->
notify_high
;
digitalWrite
(
pin_notify
,
this
->
pin_notify_state
);
this
->
ticker_notify_status
.
attach
(
this
->
notify_interval
,
this
->
notify_status_callback
,
this
);
}
void
Meteorologger
::
notify_off
(
void
)
{
this
->
pin_notify_state
=
!
this
->
notify_high
;
digitalWrite
(
pin_notify
,
this
->
pin_notify_state
);
this
->
ticker_notify_status
.
detach
();
}
nodemcu/esplogger/meteorologger.h
0 → 100644
View file @
637df50d
/*-----------------------------------------------------------------------------
* Author: Nelso G. Jost (nelsojost@gmail.com)
* License: GPLv2
* Purpose:Implements the meteorological datalog functionality.
*---------------------------------------------------------------------------*/
#ifndef METEOROLOGGER_H
#define METEOROLOGGER_H
#include <Ticker.h>
#include <SoftwareSerial.h>
#include "repl.h"
#define STATUS_LEVEL_INACTIVE 0
#define STATUS_LEVEL_OK 1
#define STATUS_LEVEL_ERROR_SWSER 2
#define STATUS_LEVEL_ERROR_SD 3
#define STATUS_LEVEL_ERROR_SERVER 4
class
Meteorologger
{
public:
Meteorologger
(
SoftwareSerial
*
arduinoSerial
,
REPL
*
repl
,
String
datalog_filename
);
String
datalog_filename
;
float
interval
=
0
;
String
command
=
""
;
String
response
=
""
;
float
arduino_threshold
=
3
;
int
pin_notify
=
2
;
bool
notify_high
=
false
;
float
notify_interval
=
5
;
float
blink_interval
=
0
.
15
;
void
activate
(
float
interval
,
String
command
);
void
update
(
void
);
void
sendCommand
(
String
command
);
protected:
int
status_level
=
STATUS_LEVEL_INACTIVE
;
bool
pin_notify_state
;
int
blink_count
=
0
;
SoftwareSerial
*
arduinoSerial
;
REPL
*
repl
;
Ticker
ticker_meteorolog
;
Ticker
ticker_arduino_threshold
;
Ticker
ticker_notify_status
;
Ticker
ticker_blink_status
;
void
notify_on
(
void
);
void
notify_off
(
void
);
static
void
meteorolog_callback
(
Meteorologger
*
m
);
static
void
arduino_threshold_callback
(
Meteorologger
*
m
);
static
void
notify_status_callback
(
Meteorologger
*
m
);
static
void
blink_status_callback
(
Meteorologger
*
m
);
};
#endif
nodemcu/esplogger/repl_meteorologger.h
0 → 100644
View file @
637df50d
#ifndef REPL_METEOROLOGGER_H
#define REPL_METEOROLOGGER_H
void
REPL_ARDUINO
(
REPL
*
repl
);
void
REPL_METEOROLOG
(
REPL
*
repl
);
void
REPL_TAILDATALOG
(
REPL
*
repl
);
#define CMD_REPL_ARDUINO { \
"arduino", \
REPL_ARDUINO, \
"arduino <command>", \
"Send command to Arduino via software serial."}
#define CMD_REPL_METEOROLOG { \
"meteorolog", \
REPL_METEOROLOG, \
"meteorolog <interval_mins> <arduino_command>", \
"Activate meterolog timer with interval (minutes)."}
#define CMD_REPL_TAILDATALOG { \
"taildatalog", \
REPL_TAILDATALOG, \
"taildatalog", \
"Print the current datalog file."}
#define ALLCMD_REPL_METEOROLOGGER \
CMD_REPL_ARDUINO, \
CMD_REPL_METEOROLOG, \
CMD_REPL_TAILDATALOG
#endif
nodemcu/esplogger/repl_sdcard.cpp
View file @
637df50d
...
...
@@ -4,13 +4,31 @@
* Purpose: Provide basic SD card management commands for the REPL.
*---------------------------------------------------------------------------*/
#include <Arduino.h>
#include "repl.h"
#include "sdcard.h"
#include "repl_sdcard.h"
void
REPL_SDINFO
(
REPL
*
repl
)
{
print_sdcard_info
();
sdcard_info
();
}
void
REPL_SDCAT
(
REPL
*
repl
)
{
sdcard_cat
(
repl
->
get_arg
(
1
));
}
void
REPL_SDTAIL
(
REPL
*
repl
)
{
sdcard_tail
(
repl
->
get_arg
(
1
));
}
void
REPL_SDWRITE
(
REPL
*
repl
)
{
sdcard_write
(
repl
->
get_arg
(
1
),
repl
->
get_arg
(
2
));
}
nodemcu/esplogger/repl_sdcard.h
View file @
637df50d
...
...
@@ -9,14 +9,34 @@
#define CMD_REPL_SDINFO {\
"sdinfo", REPL_SDINFO, "sdinfo", \
"Show a summary of the SD card info."}
"Show a summary of the SD card info including all files."}
#define CMD_REPL_SDCAT {\
"sdcat", REPL_SDCAT, "sdcat <filename>", \
"Show contents of a SD card file."}
#define CMD_REPL_SDTAIL {\
"sdtail", REPL_SDTAIL, "sdtail <filename>", \
"Show last N lines of a SD card file."}
#define CMD_REPL_SDWRITE {\
"sdwrite", REPL_SDWRITE, "sdwrite <filename> <line>", \
"Write (append) line string to a SD card file."}
#define ALLCMD_REPL_SDCARD\
CMD_REPL_SDINFO\
CMD_REPL_SDINFO, \
CMD_REPL_SDCAT, \
CMD_REPL_SDTAIL, \
CMD_REPL_SDWRITE
#include "sdcard.h"
void
REPL_SDINFO
(
REPL
*
repl
);
void
REPL_SDCAT
(
REPL
*
repl
);
void
REPL_SDTAIL
(
REPL
*
repl
);
void
REPL_SDWRITE
(
REPL
*
repl
);
#endif
nodemcu/esplogger/sdcard.cpp
View file @
637df50d
...
...
@@ -5,66 +5,78 @@
*---------------------------------------------------------------------------*/
#include <SPI.h>
#include <SD.h>
#include "sdcard.h"
Sd2Card
card
;
SdVolume
volume
;
SdFile
root
;
const
int
chipSelect
=
4
;
#include "sdcard.h"
int
__chip_select_pin
=
5
;
Sd2Card
sd_card
;
SdVolume
sd_volume
;
SdFile
sd_root
;
/* Credits:
* https://github.com/esp8266/Arduino/tree/master/libraries/SD/examples/CardInfo
*/
void
print_sdcard_info
(
void
)
void
sdcard_begin
(
int
chip_select
)
{
Serial
.
print
(
"
\n
Initializing SD card..."
);
if
(
!
SD
.
begin
(
chip_select
))
{
Serial
.
print
(
"
\n
[ERROR] Unable to initialize SD card."
);
}
__chip_select_pin
=
chip_select
;
}
if
(
!
card
.
init
(
SPI_HALF_SPEED
,
chipSelect
))
{
Serial
.
println
(
"initialization failed. Things to check:"
);
Serial
.
println
(
"* is a card inserted?"
);
Serial
.
println
(
"* is your wiring correct?"
);
Serial
.
println
(
"* did you change the chipSelect pin to match your shield or module?"
);
return
;
}
else
{
Serial
.
println
(
"Wiring is correct and a card is present."
);
}
Serial
.
print
(
"
\n
Card type: "
);
switch
(
card
.
type
())
String
sdcard_gettype
(
void
)
{
switch
(
sd_card
.
type
())
{
case
SD_CARD_TYPE_SD1
:
Serial
.
println
(
"SD1"
);
return
String
(
"SD1"
);
break
;
case
SD_CARD_TYPE_SD2
:
Serial
.
println
(
"SD2"
);
return
String
(
"SD2"
);
break
;
case
SD_CARD_TYPE_SDHC
:
Serial
.
println
(
"SDHC"
);
return
String
(
"SDHC"
);
break
;
default:
Serial
.
println
(
"Unknown"
);
return
String
(
"Unknown"
);
}
}
if
(
!
volume
.
init
(
card
))
bool
sdcard_init
(
void
)
{
if
(
!
sd_card
.
init
(
SPI_HALF_SPEED
,
__chip_select_pin
))
{
Serial
.
println
(
"
Could not find FAT16/FAT32 partition.
\n
"
"
Make sure you've formatted the card
"
);
return
;
Serial
.
println
(
"
\n
[ERROR] Unable to detect/init SD card.
"
"
Please check wiring and if card inserted.
"
);
return
false
;
}
if
(
!
sd_volume
.
init
(
sd_card
))
{
Serial
.
println
(
"
\n
[ERROR] "
+
sdcard_gettype
()
+
" card type "
"detected but with no valid FAT16/FAT32 partition"
);
return
false
;
}
return
true
;
}
/* Credits:
* https://github.com/esp8266/Arduino/tree/master/libraries/SD/examples/CardInfo
*/
void
sdcard_info
(
void
)
{
Serial
.
println
(
"
\n
Initializing SD card.."
);
if
(
!
sdcard_init
())
return
;
Serial
.
println
(
"
\n
"
+
sdcard_gettype
()
+
" card type detected."
);
uint32_t
volumesize
;
Serial
.
print
(
"
\n
Volume type is FAT"
);
Serial
.
println
(
volume
.
fatType
(),
DEC
);
Serial
.
println
(
sd_
volume
.
fatType
(),
DEC
);
Serial
.
println
();
volumesize
=
volume
.
blocksPerCluster
();
// clusters are collections of blocks
volumesize
*=
volume
.
clusterCount
();
// we'll have a lot of clusters
volumesize
=
sd_
volume
.
blocksPerCluster
();
// clusters are collections of blocks
volumesize
*=
sd_
volume
.
clusterCount
();
// we'll have a lot of clusters
volumesize
*=
512
;
// SD card blocks are always 512 bytes
Serial
.
print
(
"Volume size (bytes): "
);
Serial
.
println
(
volumesize
);
...
...
@@ -76,9 +88,96 @@ void print_sdcard_info(void)
Serial
.
println
(
volumesize
);
Serial
.
println
(
"
\n
Files found on the card (name, date and size in bytes): "
);
root
.
openRoot
(
volume
);
sd_root
.
openRoot
(
sd_
volume
);
// list all files in the card with date and size
root
.
ls
(
LS_R
|
LS_DATE
|
LS_SIZE
);
sd_root
.
ls
(
LS_R
|
LS_DATE
|
LS_SIZE
);
}
bool
sdcard_cat
(
String
filename
)
{
if
(
!
sdcard_init
())
return
false
;
File
sd_file
=
SD
.
open
(
filename
.
c_str
(),
FILE_READ
);
if
(
!
sd_file
)
{
Serial
.
println
(
"
\n
[ERROR] Unable to open '"
+
filename
+
"'"
);
return
false
;
}
Serial
.
print
(
"
\n
------------------------------------------
\n
"
);
while
(
sd_file
.
available
())
Serial
.
write
(
sd_file
.
read
());
Serial
.
print
(
"
\n
------------------------------------------
\n
"
);
sd_file
.
close
();
return
true
;
}
bool
sdcard_tail
(
String
filename
)
{
if
(
!
sdcard_init
())
return
false
;
File
sd_file
=
SD
.
open
(
filename
.
c_str
(),
FILE_READ
);
if
(
!
sd_file
)
{
Serial
.
println
(
"
\n
[ERROR] Unable to open '"
+
filename
+
"'"
);
return
false
;
}
Serial
.
print
(
"
\n
------------------------------------------
\n
"
);
char
c
;
int
line_count
=
0
;
int
pos
=
sd_file
.
size
()
-
1
;
int
first_line
=
0
;
sd_file
.
seek
(
pos
);
while
(
sd_file
.
available
())
{
c
=
sd_file
.
read
();
if
(
c
==
'\n'
)