How to access Moteino FLASH when externally (battery) powered

Started by gkientzy, March 04, 2015, 02:50:38 PM

gkientzy

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.

TomWS

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

Felix

@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.

gkientzy

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.
// **********************************************************************************
// 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);
//  }
}

Felix

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);

gkientzy

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);

}

Felix

See this post.
Also see this post

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.

gkientzy

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.

Felix

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?

gkientzy

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. 

gkientzy

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.

gkientzy

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?

TomWS

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

Felix

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.

TomWS

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.