I am using flash to store a unique Device ID (address 0x00) , rather than using hard coded values. My program works fine when connected and powering the Moteino through the FTDI adapter. My final solution needs to run from battery. When I connect the Moteino based product to 4 AA batteries (Eneloop), the program no longer works. I have traced the issue to the flash.readbyte command. While I can't monitor (since USB is no longer connected) the program flow, when I hardcode the Device ID, everything works as it should. The function call being used is really simple as follows:
device_id=flash.readByte(0);
The question is whether the flash device (read or write) functions differently when the moteino is powered externally? Any help would be appreciated. Thanks.
Quote from: gkientzy on March 04, 2015, 02:50:38 PM
I am using flash to store a unique Device ID (address 0x00) , rather than using hard coded values. My program works fine when connected and powering the Moteino through the FTDI adapter. My final solution needs to run from battery. When I connect the Moteino based product to 4 AA batteries (Eneloop), the program no longer works. I have traced the issue to the flash.readbyte command. While I can't monitor (since USB is no longer connected) the program flow, when I hardcode the Device ID, everything works as it should. The function call being used is really simple as follows:
device_id=flash.readByte(0);
The question is whether the flash device (read or write) functions differently when the moteino is powered externally? Any help would be appreciated. Thanks.
Flash requires SPI to access, with a certain amount of setup required. Also, the first 32K of your flash will get erased by the bootloader (I'm not sure if it's at every boot or just after a wireless update), but address 0 is not a good address to use. Secondly, I recommend using EEPROM to store this kind of information. It's easier to use and is NOT used by the RFM69 libraries or bootloader.
Finally, if you do use any flash to store constants like this, include a checksum and/or signature so that you know that the memory has been initialized. If you discover that it hasn't you can fallback to hardcoded values...
Tom
@gkientzy It has no reason not to work when powered externally, provided there is at least 3.5V on the VIN of the Moteino (your post suggests you are using a LowPowerLab Moteino).
@Tom - the first 32k sector only ever gets erased after wireless programming happens, it never touches any of the flash memory otherwise.
I am using Moteino devices. I have tried on two separate Moteino units.
I took one of your example projects and modified to demonstrate my problem. Again, I can read flash just fine USB powered (from development platform), but cannot do so battery powered (4 AA batteries or 5V wall wart). You will see the modified code below - it was simply modified to flash LED on successful read of flash (value 3 in 0x00 location). Thank you for your support.
Adapted from this sketch (https://github.com/LowPowerLab/SPIFlash/blob/master/examples/SPIFlash_ReadWrite/SPIFlash_ReadWrite.ino).
// **********************************************************************************
// This sketch is an example of using the SPIFlash library with a Moteino
// **********************************************************************************
#include <SPIFlash.h> //get it here: https://github.com/LowPowerLab/SPIFlash
#include <SPI.h>
#define SERIAL_BAUD 115200
char input = 0;
long lastPeriod = -1;
int count;
#ifdef __AVR_ATmega1284P__
#define LED 15 // Moteino MEGAs have LEDs on D15
#define FLASH_SS 23 // and FLASH SS on D23
#else
#define LED 9 // Moteinos have LEDs on D9
#define FLASH_SS 8 // and FLASH SS on D8
#endif
//////////////////////////////////////////
// flash(SPI_CS, MANUFACTURER_ID)
// SPI_CS - CS pin attached to SPI flash chip (8 in case of Moteino)
// MANUFACTURER_ID - OPTIONAL, 0x1F44 for adesto(ex atmel) 4mbit flash
// 0xEF30 for windbond 4mbit flash
//////////////////////////////////////////
SPIFlash flash(FLASH_SS, 0xEF30);
void setup(){
Serial.begin(SERIAL_BAUD);
Serial.print("Start...");
if (flash.initialize())
Serial.println("Init OK!");
else
Serial.println("Init FAIL!");
}
void loop(){
// Handle serial input (to allow basic DEBUGGING of FLASH chip)
// ie: display first 256 bytes in FLASH, erase chip, write bytes at first 10 positions, etc
if (Serial.available() > 0) {
input = Serial.read();
if (input == 'd') //d=dump flash area
{
Serial.println("Flash content:");
int counter = 0;
while(counter<=10){
Serial.print(flash.readByte(counter++), HEX);
Serial.print('.');
}
Serial.println();
}
else if (input == 'e')
{
Serial.print("Erasing Flash chip ... ");
flash.chipErase();
while(flash.busy());
Serial.println("DONE");
}
else if (input == 'i')
{
Serial.print("DeviceID: ");
Serial.println(flash.readDeviceId(), HEX);
}
else if (input >= 48 && input <= 57) //0-9
{
Serial.print("\nWriteByte("); Serial.print(input); Serial.print(")");
flash.writeByte(0, input-48);
}
}
count=(int) flash.readByte(0x00);
// count=3;
Serial.print("Count="); Serial.println(count);
if (count==3) {
digitalWrite(9, HIGH);
delay(2000);
}
digitalWrite(9, LOW);
delay(2000);
// // Periodically blink the onboard LED while listening for serial commands
// if ((int)(millis()/500) > lastPeriod)
// {
// lastPeriod++;
// pinMode(9, OUTPUT);
// digitalWrite(9, lastPeriod%2);
// }
}
How do you expect the LED to blink if it's an INPUT?
You missed making it an output. Adding this will make the sketch actually blink. This was tested on battery and it works, but not before adding this:
pinMode(LED, OUTPUT);
Felix, sorry for the oversight on not making the LED pin an output. An oversight on my part on a modified example meant to demonstrate the problem. Unfortunately, this change did not solve my root issue. I have done some further troubleshooting and found that the "externally" powered Moteino never returns from the flash.initialize() function, thereby allowing the LED to be turned off. Flashing of LED around the flash.initialize function is in the setup() function. I am using the lib found at https://github.com/LowPowerLab/SPIFlash. Any help/insight you can provide would be appreciated.
// This sketch is an example of using the SPIFlash library with a Moteino
// that has an onboard SPI Flash chip. This sketch listens to a few serial commands
// Hence type the following commands to interact with the SPI flash memory array:
// - 'd' dumps the first 256bytes of the flash chip to screen
// - 'e' erases the entire memory chip
// - 'i' print manufacturer/device ID
// - [0-9] writes a random byte to addresses [0-9] (either 0xAA or 0xBB)
// Get the SPIFlash library from here: https://github.com/LowPowerLab/SPIFlash
// **********************************************************************************
// Copyright Felix Rusu, LowPowerLab.com
// Library and code by Felix Rusu - [email protected]
#include <SPIFlash.h> //get it here: https://github.com/LowPowerLab/SPIFlash
#include <SPI.h>
#define SERIAL_BAUD 115200
char input = 0;
long lastPeriod = -1;
int count;
#ifdef __AVR_ATmega1284P__
#define LED 15 // Moteino MEGAs have LEDs on D15
#define FLASH_SS 23 // and FLASH SS on D23
#else
#define LED 9 // Moteinos have LEDs on D9
#define FLASH_SS 8 // and FLASH SS on D8
#endif
SPIFlash flash(FLASH_SS, 0xEF30);
void setup(){
Serial.begin(SERIAL_BAUD);
Serial.print("Start...");
pinMode(LED, OUTPUT);
digitalWrite(LED, HIGH);
delay(5000);
if (flash.initialize()) //Comment these 4 lines out is only way that LED does 5 second ON/OFF flash on Battery.
Serial.println("Init OK!");
else
Serial.println("Init FAIL!");
digitalWrite(LED, LOW);
delay(5000);
}
void loop(){
if (Serial.available() > 0) {
input = Serial.read();
if (input == 'd') //d=dump flash area
{
Serial.println("Flash content:");
int counter = 0;
while(counter<=10){
Serial.print(flash.readByte(counter++), HEX);
Serial.print('.');
}
Serial.println();
}
else if (input == 'e')
{
Serial.print("Erasing Flash chip ... ");
flash.chipErase();
while(flash.busy());
Serial.println("DONE");
}
else if (input == 'i')
{
Serial.print("DeviceID: ");
Serial.println(flash.readDeviceId(), HEX);
}
else if (input >= 48 && input <= 57) //0-9
{
Serial.print("Probe Device ID: "); Serial.println(input);
Serial.println();
flash.blockErase4K(0);
while(flash.busy());
flash.writeByte(0, (input-48));
}
}
count=(int) flash.readByte(0x00);
while(flash.busy());
// count=3;
if (count==3) {
digitalWrite(LED, HIGH);
delay(2000);
}
digitalWrite(LED, LOW);
delay(2000);
}
See this post (https://lowpowerlab.com/forum/index.php/topic,857.0.html).
Also see this post (https://lowpowerlab.com/forum/index.php/topic,652.0.html)
Can you try a 10K pulldown on the MISO line to see if that solves your issue? Explanation below.
There is a while(busy()); call in the readByte() function of the library. This waits for any write/erase to complete.
A time limit cannot really be added here without it being a very large safe limit.
That is because some chips can take several seconds to carry out a chip erase or other similar multi block or entire-chip operations.
A recommended alternative to such situations where chip can be or not be present is to add a 10k or similar weak pulldown on the open drain MISO input which can read noise/static and hence return a non 0 status byte, causing the while() to hang when a flash chip is not present.
Felix, the 10K pulldown was added with no effect. Running on battery, the Moteino never returns from the flash.initialize() function. Any other suggestions? I am assuming you and others have developed battery based Moteino solutions which access the flash, leaving me wondering if it is my Moteino(s) only? BTW, I am doing my testing on bare Moteinos to eliminate as many variables as possible.
Yes I did my own testing and I see no such effect.
Did you test with only 1 Moteino? If so can you try another?
I have tested using two Moteinos, neither which can access flash while powered from battery. BTW, I have the R4 version of Moteino (without USB). I am also using the Arduino 1.6.0 IDE for what that is worth.
In further tests, I powered the Moteino through the FTDI adapter (from Lowpowerlab) using a 5V/1A power adapter (as opposed to Vin and Gnd using battery). The results were the same as if on battery in not returning from the flash.initialize function. Could the state of the serial lines (CTS, DTR, TX or RX) have any impact? They shouldn't but I don't know what else it could be. I will do further testing. The lowpowerlab FTDI adapter jumper settings are as from factory.
Felix, as a followup, when I pull the DTR pin to low on the Moteino, the program executes as it should, no longer hanging in the flash.initialize() function when externally powered. Any idea why this could be?
Quote from: gkientzy on March 06, 2015, 12:11:52 PM
Felix, as a followup, when I pull the DTR pin to low on the Moteino, the program executes as it should, no longer hanging in the flash.initialize() function when externally powered. Any idea why this could be?
I don't know what is causing your problem, but holding DTR low effectively puts a capacitor between ground and the reset pin. Given that this seems to get things working, I'm inclined to look into noisy power lines. Since you're working from batteries, is it possible the lines are intermittent or corroded contacts? Just some thoughts...
Tom
Yeah this is weird, I can't replicate this problem, using the same code and running on battery, or on USB, makes no difference - it blinks in both cases.
Pulling DTR low causes it to reset so there's something special/different in your setup. Sometimes a detailed photo helps identify the source of the problem.
Can you simply try a blinky sketch that blinks the LED a few times in the setup() function without any FLASH checking or anything else? Don't forget the LED must be declared OUTPUT.
Also can you visually inspect them for any shorts between the atmega pins? This should be a very rare occurence and almost impossible in 2 moteinos back to back but do check anyway. A detailed photo would be nice.
Quote from: Felix on March 07, 2015, 01:24:23 PM
...
Pulling DTR low causes it to reset so there's something special/different in your setup.
...
Holding DTR low won't keep it in reset state. The pullup resistor on the reset pin will pull it out of reset and then the capacitor will act merely as a noise filter on the reset pin. I still lean toward noisy power source.
Guys,
So...I'm still trying to track down my power consumption issue, and I'm trying to follow your recommendations to put the radio and flash (which doesn't exist) to sleep. In the process, I'm running into this exact issue. When I power the Moteino through the FTDI plugged into my PC, it behaves as expected. However, when I use the same USB cable but disconnect it from my computer and plug it into a wall wart adapter, the sketch hangs at flash.initialize(). The sketch also hangs if I instead use a 3.7V LiPo (measuring 4.2 on the multimeter). I've connected a 10k pulldown resistor between MISO and ground, as recommended in this and other posts. I tested using the sketch here:
https://github.com/LowPowerLab/SPIFlash/issues/4 (https://github.com/LowPowerLab/SPIFlash/issues/4)
Without the pulldown, readStatus() would occasionally return 255, but the pulldown seemed to more reliably make it return 0. However, I clearly can't test this with serial output when battery powered. Thoughts?
If your Moteino doesn't have flash installed then don't use the SPIflash Library or instantiate a flash device. This advice was given assuming you had a full Moteino configuration, which included flash.
If your FTDI cable is not connected to a PC then I wouldn't use it as the power source to your Moteino - there could be many reasons why this hangs. However, I am curious to know how you know that your code hangs at flash.initialize() if you don't have a debug port attached (ie, the FTDI cable is plugged into a wall wart). In any case, if you use a wall wart, just use a direct USB A to wire or DC jack type cable.
See if it your Mote still hangs if you remove the flash code and power with wall wart and/or battery and let us know. Also, as I mentioned in this thread, simply connecting DTR to ground (the two outer pins on the FTDI connector - WITHOUT the FTDI cable installed, of course) sometimes resolves some power on issues.
Tom
Thanks, Tom. My typical debug-without-serial technique is to use LED flashing. I put a few LED flashes directly the flash.initialize, which never flash when using a battery/wall wart. When I comment out the flash lines, everything works fine, regardless of the power source. Odd behavior. I don't understand why powering off the FTDI using a wall wart would be an issue. Looking at the Moteino schematic, the FTDI VIN is connected directly to the VIN pin, so why would that make any difference? Besides the weird flash behavior, everything else works fine.
As a side note, today everything works fine in terms of power consumption (kind of). I've finally reached ~25uA when asleep! I'll post more about that in the other forum.
Quote from: mattmunee on June 27, 2015, 01:36:30 PM
<snip> I don't understand why powering off the FTDI using a wall wart would be an issue. Looking at the Moteino schematic, the FTDI VIN is connected directly to the VIN pin, so why would that make any difference? Besides the weird flash behavior, everything else works fine.
The FTDI chip is still driving the RX & DTR pins when powered but not initialized via USB. FTDI doesn't document this condition so I have no idea what the pins are doing in this state. Best to leave them disconnected altogether.
Tom