Skip to content

Commit ef33b88

Browse files
committed
Add file write testing with power down
1 parent 799ea30 commit ef33b88

File tree

2 files changed

+329
-0
lines changed

2 files changed

+329
-0
lines changed
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
/*
2+
Power down all parts of the board
3+
Wake after three seconds
4+
Write to a file
5+
Power back down
6+
*/
7+
8+
//#include <Wire.h>
9+
10+
//microSD Interface
11+
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
12+
#include <SPI.h>
13+
#include <SdFat.h> //We use SdFat-Beta from Bill Greiman for increased read/write speed
14+
15+
const byte PIN_MICROSD_CHIP_SELECT = 10;
16+
const byte PIN_MICROSD_POWER = 15; //x04
17+
18+
#define SD_CONFIG SdSpiConfig(PIN_MICROSD_CHIP_SELECT, SHARED_SPI, SD_SCK_MHZ(24)) //Max of 24MHz
19+
#define SD_CONFIG_MAX_SPEED SdSpiConfig(PIN_MICROSD_CHIP_SELECT, DEDICATED_SPI, SD_SCK_MHZ(24)) //Max of 24MHz
20+
21+
SdFat sd;
22+
File sensorDataFile; //File that all sensor data is written to
23+
File serialDataFile; //File that all incoming serial data is written to
24+
25+
char sensorDataFileName[30] = ""; //We keep a record of this file name so that we can re-open it upon wakeup from sleep
26+
char serialDataFileName[30] = ""; //We keep a record of this file name so that we can re-open it upon wakeup from sleep
27+
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
28+
29+
uint32_t msToSleep = 3000; //This is the user editable number of ms to sleep between RTC checks
30+
#define TIMER_FREQ 32768L //Counter/Timer 6 will use the 32kHz clock
31+
uint32_t sysTicksToSleep = msToSleep * TIMER_FREQ / 1000;
32+
33+
const byte PIN_QWIIC_POWER = 18;
34+
const byte PIN_STAT_LED = 19;
35+
const byte PIN_IMU_POWER = 22;
36+
37+
void setup(void) {
38+
Serial.begin(115200);
39+
Serial.println();
40+
Serial.println("SD Write Test");
41+
42+
qwiicPowerOff();
43+
microSDPowerOff();
44+
imuPowerOff();
45+
46+
SPI.begin();
47+
48+
beginSD();
49+
50+
beginDataLogging();
51+
52+
Serial.println("Setup done");
53+
}
54+
55+
void loop(void)
56+
{
57+
String outputData = "Test string\n";
58+
59+
char temp[512];
60+
outputData.toCharArray(temp, 512); //Convert string to char array so sdfat can record it
61+
sensorDataFile.write(temp, strlen(temp)); //Record the buffer to the card
62+
sensorDataFile.sync();
63+
64+
Serial.println("File recorded");
65+
66+
goToSleep();
67+
}
68+
69+
//Power everything down and wait for RTC interrupt wakeup
70+
void goToSleep()
71+
{
72+
//digitalWrite(LOGIC_DEBUG, HIGH);
73+
74+
Serial.flush();
75+
Serial.end(); //Power down UART
76+
77+
power_adc_disable(); //Power down ADC
78+
79+
for (int x = 0 ; x < 50 ; x++)
80+
am_hal_gpio_pinconfig(x , g_AM_HAL_GPIO_DISABLE);
81+
82+
qwiicPowerOff();
83+
microSDPowerOff();
84+
imuPowerOff();
85+
86+
//We use counter/timer 6 to cause us to wake up from sleep but 0 to 7 are available
87+
//CT 7 is used for Software Serial. All CTs are used for Servo.
88+
am_hal_stimer_int_clear(AM_HAL_STIMER_INT_COMPAREG); //Clear CT6
89+
am_hal_stimer_int_enable(AM_HAL_STIMER_INT_COMPAREG); //Enable C/T G=6
90+
91+
//Use the lower power 32kHz clock
92+
am_hal_stimer_config(AM_HAL_STIMER_CFG_CLEAR | AM_HAL_STIMER_CFG_FREEZE);
93+
am_hal_stimer_config(AM_HAL_STIMER_XTAL_32KHZ | AM_HAL_STIMER_CFG_COMPARE_G_ENABLE);
94+
95+
//Right here we need to reduce the sleep sys ticks by the amount we've been awake so that we hit exactly 0.12Hz
96+
97+
//Setup interrupt to trigger when the number of ms have elapsed
98+
am_hal_stimer_compare_delta_set(6, sysTicksToSleep);
99+
100+
// Turn OFF Flash1
101+
am_hal_pwrctrl_memory_enable(AM_HAL_PWRCTRL_MEM_FLASH_512K);
102+
103+
// Power down SRAM
104+
// Nathan seems to have gone a little off script here and isn't using
105+
// am_hal_pwrctrl_memory_deepsleep_powerdown or
106+
// am_hal_pwrctrl_memory_deepsleep_retain. I wonder why?
107+
//PWRCTRL->MEMPWDINSLEEP_b.SRAMPWDSLP = PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_ALLBUTLOWER32K;
108+
PWRCTRL->MEMPWDINSLEEP_b.SRAMPWDSLP = PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_ALLBUTLOWER64K;
109+
110+
//Enable the timer interrupt in the NVIC.
111+
NVIC_EnableIRQ(STIMER_CMPR6_IRQn);
112+
113+
// Go to Deep Sleep.
114+
am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);
115+
116+
//Turn off interrupt
117+
NVIC_DisableIRQ(STIMER_CMPR6_IRQn);
118+
119+
//We're BACK!
120+
wakeFromSleep();
121+
}
122+
123+
//Power everything up gracefully
124+
void wakeFromSleep()
125+
{
126+
// Set the clock frequency. (redundant?)
127+
am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0);
128+
129+
// Set the default cache configuration. (redundant?)
130+
am_hal_cachectrl_config(&am_hal_cachectrl_defaults);
131+
am_hal_cachectrl_enable();
132+
133+
// Note: because we called setupRTC earlier,
134+
// we do NOT want to call am_bsp_low_power_init() here.
135+
// It would configure the board for low power operation
136+
// and calls am_hal_pwrctrl_low_power_init()
137+
// but it also stops the RTC oscillator!
138+
// (BSP = Board Support Package)
139+
140+
// Initialize for low power in the power control block. (redundant?)
141+
am_hal_pwrctrl_low_power_init();
142+
143+
// Power up SRAM
144+
PWRCTRL->MEMPWDINSLEEP_b.SRAMPWDSLP = PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_NONE;
145+
146+
// Turn on Flash
147+
// There is a chance this could fail but I guess we should move on regardless and not do a while(1);
148+
am_hal_pwrctrl_memory_enable(AM_HAL_PWRCTRL_MEM_ALL);
149+
150+
// Go back to using the main clock
151+
am_hal_stimer_int_enable(AM_HAL_STIMER_INT_OVERFLOW); // (posssibly redundant?)
152+
NVIC_EnableIRQ(STIMER_IRQn); // (posssibly redundant?)
153+
am_hal_stimer_config(AM_HAL_STIMER_CFG_CLEAR | AM_HAL_STIMER_CFG_FREEZE);
154+
am_hal_stimer_config(AM_HAL_STIMER_HFRC_3MHZ);
155+
156+
// Restore the TX/RX connections between the Artemis module and the CH340S
157+
am_hal_gpio_pinconfig(48 /* TXO-0 */, g_AM_BSP_GPIO_COM_UART_TX);
158+
am_hal_gpio_pinconfig(49 /* RXI-0 */, g_AM_BSP_GPIO_COM_UART_RX);
159+
160+
// Reenable the debugger GPIOs
161+
am_hal_gpio_pinconfig(20 /* SWDCLK */, g_AM_BSP_GPIO_SWDCK);
162+
am_hal_gpio_pinconfig(21 /* SWDIO */, g_AM_BSP_GPIO_SWDIO);
163+
164+
// Turn on ADC
165+
ap3_adc_setup();
166+
167+
// Start the console serial port again (zzz will have ended it)
168+
Serial.begin(115200);
169+
Serial.println("Back on");
170+
171+
}
172+
173+
//Called once number of milliseconds has passed
174+
extern "C" void am_stimer_cmpr6_isr(void)
175+
{
176+
uint32_t ui32Status = am_hal_stimer_int_status_get(false);
177+
if (ui32Status & AM_HAL_STIMER_INT_COMPAREG)
178+
{
179+
am_hal_stimer_int_clear(AM_HAL_STIMER_INT_COMPAREG);
180+
}
181+
}
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
//Returns next available log file name
2+
//Checks the spots in EEPROM for the next available LOG# file name
3+
//Updates EEPROM and then appends to the new log file.
4+
char* findNextAvailableLog(int &newFileNumber, const char *fileLeader)
5+
{
6+
File newFile; //This will contain the file for SD writing
7+
8+
Serial.println("Next avail");
9+
Serial.flush();
10+
11+
if (newFileNumber > 0)
12+
newFileNumber--; //Check if last log file was empty
13+
14+
//Search for next available log spot
15+
static char newFileName[40];
16+
while (1)
17+
{
18+
Serial.println("1");
19+
Serial.flush();
20+
21+
sprintf(newFileName, "%s%05u.TXT", fileLeader, newFileNumber); //Splice the new file number into this file name
22+
23+
Serial.println("2");
24+
Serial.flush();
25+
26+
Serial.println(newFileName);
27+
Serial.flush();
28+
29+
if (sd.exists(newFileName) == false) break; //File name not found so we will use it.
30+
31+
Serial.println("3");
32+
Serial.flush();
33+
34+
//File exists so open and see if it is empty. If so, use it.
35+
newFile = sd.open(newFileName, O_READ);
36+
//newFile.open(newFileName, O_READ); //exFat
37+
if (newFile.size() == 0) break; // File is empty so we will use it.
38+
39+
Serial.println("4");
40+
Serial.flush();
41+
42+
newFile.close(); // Close this existing file we just opened.
43+
44+
newFileNumber++; //Try the next number
45+
}
46+
Serial.println("5");
47+
Serial.flush();
48+
newFile.close(); //Close this new file we just opened
49+
50+
Serial.println("6");
51+
Serial.flush();
52+
newFileNumber++; //Increment so the next power up uses the next file #
53+
//recordSettings(); //Record new file number to EEPROM and to config file
54+
55+
Serial.print(F("Created log file: "));
56+
Serial.println(newFileName);
57+
Serial.flush();
58+
59+
return (newFileName);
60+
}
61+
62+
void beginDataLogging()
63+
{
64+
int fileNumber = 10;
65+
66+
//If we don't have a file yet, create one. Otherwise, re-open the last used file
67+
if (strlen(sensorDataFileName) == 0)
68+
strcpy(sensorDataFileName, findNextAvailableLog(fileNumber, "dataLog"));
69+
70+
// O_CREAT - create the file if it does not exist
71+
// O_APPEND - seek to the end of the file prior to each write
72+
// O_WRITE - open for write
73+
if (sensorDataFile.open(sensorDataFileName, O_CREAT | O_APPEND | O_WRITE) == false)
74+
{
75+
Serial.println("Failed to create sensor data file");
76+
return;
77+
}
78+
79+
Serial.println("Sensor data file open");
80+
Serial.flush();
81+
}
82+
83+
void beginSD()
84+
{
85+
pinMode(PIN_MICROSD_CHIP_SELECT, OUTPUT);
86+
digitalWrite(PIN_MICROSD_CHIP_SELECT, HIGH); //Be sure SD is deselected
87+
88+
microSDPowerOn();
89+
90+
//Max power up time is 250ms: https://www.kingston.com/datasheets/SDCIT-specsheet-64gb_en.pdf
91+
//Max current is 200mA average across 1s, peak 300mA
92+
delay(10);
93+
94+
if (sd.begin(SD_CONFIG) == false) //Slightly Faster SdFat Beta (we don't have dedicated SPI)
95+
{
96+
delay(250); //Give SD more time to power up, then try again
97+
if (sd.begin(SD_CONFIG) == false) //Slightly Faster SdFat Beta (we don't have dedicated SPI)
98+
{
99+
Serial.println("SD init failed. Do you have the correct board selected in Arduino? Is card present? Formatted?");
100+
digitalWrite(PIN_MICROSD_CHIP_SELECT, HIGH); //Be sure SD is deselected
101+
return;
102+
}
103+
}
104+
// }
105+
106+
//Change to root directory. All new file creation will be in root.
107+
if (sd.chdir() == false)
108+
{
109+
Serial.println("SD change directory failed");
110+
return;
111+
}
112+
113+
Serial.println("SD begin complete");
114+
Serial.flush();
115+
}
116+
117+
void qwiicPowerOn()
118+
{
119+
pinMode(PIN_QWIIC_POWER, OUTPUT);
120+
digitalWrite(PIN_QWIIC_POWER, LOW);
121+
}
122+
void qwiicPowerOff()
123+
{
124+
pinMode(PIN_QWIIC_POWER, OUTPUT);
125+
digitalWrite(PIN_QWIIC_POWER, HIGH);
126+
}
127+
128+
void microSDPowerOn()
129+
{
130+
pinMode(PIN_MICROSD_POWER, OUTPUT);
131+
digitalWrite(PIN_MICROSD_POWER, LOW);
132+
}
133+
void microSDPowerOff()
134+
{
135+
pinMode(PIN_MICROSD_POWER, OUTPUT);
136+
digitalWrite(PIN_MICROSD_POWER, HIGH);
137+
}
138+
139+
void imuPowerOn()
140+
{
141+
pinMode(PIN_IMU_POWER, OUTPUT);
142+
digitalWrite(PIN_IMU_POWER, HIGH);
143+
}
144+
void imuPowerOff()
145+
{
146+
pinMode(PIN_IMU_POWER, OUTPUT);
147+
digitalWrite(PIN_IMU_POWER, LOW);
148+
}

0 commit comments

Comments
 (0)