Page 3 of 4

Re: Power Consumption

Posted: Thu Nov 24, 2016 2:32 pm
by kekeller
I spent some time working on the STM32 firmware. I was able to drop the power by about 20 mW but the other changes broke the system like you suggested (dropping frequency, etc.)
That being said I think reaching 100mW (about 27mA) will be difficult. Then I think the system would have to work in an on/off manner but I'm not sure the sensors could handle that.
This is currently the plan we are pursing. We want to start power cycling the STM32 from the NRF51. Yes - the radio will break, and the sensors will not work that well but for the code we want to run on the blimp this will be fine. We are basically just looking at some motor control. Again - this all exploring some low power system designs.

What's the best way to get the NRF51 to power cycle? I was looking at just setting up a timer on the NRF that would fire and set the STM boot pins, and then turn them off after a set amount of time again.

Based on the existing firmware - is there a better method for this? There's also the option of adding some code in the button event handling to periodically reboot the STM.

Re: Power Consumption

Posted: Fri Nov 25, 2016 10:16 am
by arnaud
The nRF51 has control of the STM32 power supply, so it is possible to shut-off the STM32 and keep the radio and nRF51 running normally (though radio packet routing to STM32 will off course not work). The pm.c file implement that functionality so calling pmSetState(pmSysOff) will cut power to the STM32, sensors and expansion port VCC3V. Calling pmSetState(pmSysRunning) will switch it back-on. Is that what you are after?

Re: Power Consumption

Posted: Tue Nov 29, 2016 8:55 am
by tobias
I would say the difficulty lies in making the STM firmware work in an periodic manner. E.g. now there is calibration going on during startup and the sensor fusion filters have a settlement time. This might be difficult to handle so I'm not so sure it is such a good idea. The STM has a battery backed up memory so it is possible to save states etc but it will be a challenge to make it work. Thinking about it I'm leaning towards it is easier to lower the STM clock speed and make that work. Also disabling all power consuming peripherals that isn't used.

Re: Power Consumption

Posted: Mon Dec 05, 2016 6:21 pm
by kekeller
I ended up going with the power cycle version of the code that looks like this. It works super well for what we need.

On the STM I am running a super simple motor control program inside the stabilizer task. In the future we will expand this a bit and maybe save state to memory during the on period or something. But at the moment this is what we need.

Code: Select all

    // power cycle off if the ON time has been reached
    else if ((pmGetState() == pmSysRunning) && ((systickGetTick() - powerTick) >= TICK_BETWEEN_POWER_ON))
    {
      powerTick = systickGetTick();
      LED_OFF();
      //stm bootloader
      pmSysBootloader(true);
      pmSetState(pmSysOff); // turn off system
      
    } 

    // power cycle on if on_flag set in low power timer is set
    else if ((pmGetState() == pmSysOff) && ((systickGetTick() - powerTick) >= TICK_BETWEEN_POWER_OFF))
    {
      powerTick = systickGetTick(); // get tick to start again
      LED_ON();
      //stm bootloader 
      pmSysBootloader(false);
      pmSetState(pmSysRunning); // turn system on      
    } 
I do have one last question. During the 'off' state, it's still pulling a bunch of current. I've spent the past week trying to set it to sleep and it's not working. Actually sleeping is not an issue. I tested it and it's pulling in the micro amp range. The issue is the timer interrupt. The sleep wakes during the interrupt so the 1ms timer does not work. I wrote a second timer (timer0) that could sleep for n number of seconds when started. That works fine. I tested it in main by commenting everything else out and just toggeling the LED each interrupt.

Code: Select all

// Make sure any pending events are cleared
      //__SEV();
      //__WFE(); // go to sleep until interrupt wakes
      //__WFE(); 
I then modified the power cycling to look like this:

Code: Select all

    // power cycle off if the ON time has been reached
    else if ((pmGetState() == pmSysRunning) && ((systickGetTick() - powerTick) >= TICK_BETWEEN_POWER_ON))
    { 
      LED_OFF();
      //stm bootloader
      pmSysBootloader(true);
      pmSetState(pmSysOff); // turn off system
      timer0_init(5000);  // 5 second timer - working

      // Make sure any pending events are cleared
      //__SEV();
      //__WFE(); // go to sleep until interrupt wakes
      //__WFE(); 
    } 

    // power cycle on if on_flag set in low power timer is set
    else if ((pmGetState() == pmSysOff) && on_flag)
    {
      on_flag = false;
      systickInit(1000); // start normal tick timer again and turn off timer0
      LED_ON();
      //stm bootloader 
      pmSysBootloader(false);
      pmSetState(pmSysRunning); // turn system on
    } */
on_flag is getting set each time the timer0 interrupt hits. And inside of timer0_init() I turn off timer 2 and start timer 0. But the system enters indeterminate state. I think this is due to the lack of 'tick' timer to run the pmProcess() and it gets stuck.

I tried a number of different ideas with turning the two timers on and off and setting flags to wake/sleep but it usually enters a strange state. Do you have any ideas about the best way to get it sleep when the main STM32 is off? I assume there are a number of ways to solve this problem and my approach is not working ;)

Re: Power Consumption

Posted: Tue Dec 06, 2016 8:45 am
by tobias
That is great that you manage to get something to work!

So how do you get around the sensor calibrations etc, or you don't use it at all maybe? Another thing that came to my mind would be to let the MPU9250 do the sensor fusion using its MPU and letting the STM32 put itself in off mode with periodic wake up, thus keeping the VCC enabled but cutting the biggest consumer, STM32.

As for the wake-up part I've never tried it with a timer myself so don't have much to add :oops:. I'm guessing NordicSemi must have examples of this?

Re: Power Consumption

Posted: Tue Dec 06, 2016 10:28 am
by kekeller
Sensor calibration was removed. It required a stable platform and we are attaching the CF to a balloon so it was never stable during flight so it would never pass calibration.
Another thing that came to my mind would be to let the MPU9250 do the sensor fusion using its MPU and letting the STM32 put itself in off mode with periodic wake up, thus keeping the VCC enabled but cutting the biggest consumer, STM32.
That's a good idea - I don't think we are going to approach that at this time. But we will keep it in mind for the future.

No worries about the timer. I checked with the Nordic Documentation and the forum and I think I am on the right track. The issue is just getting multiple systems to work together :oops:

Re: Power Consumption

Posted: Tue Dec 06, 2016 7:04 pm
by kekeller
I got the sleep working! And broke the booting....

Since the goal is just to power cycle the STM and then sleep during off time I figured we could just directly do that in main and bypass the state machine in pmProcess();

This works to cycle between sleep and active mode using timer 0 (boot flag set in initialization function). The issue is actually getting the STM to boot. I am using the original firmware on the STM to avoid possible bugs from my changes.

The code turns the VCC power on and off (checked with meter at 2.99V). But the STM never boots?

Which step in the boot process am I missing? I thought I had grabbed the relevant commands from the state machine.

Code: Select all

int main() 
{  
  timer0_init(15000); // set 15 second interrupt timer to toggle boot_flag
  LED_INIT();
  LED_OFF();
  while (1) {
    if (boot_flag == true) {
      LED_ON();
      pmPowerSystem(true);
      pmSysBootloader(true);
      pmRunSystem(true);
    }
    if (boot_flag == false) {
      LED_OFF();
      pmSysBootloader(false);
      pmPowerSystem(false);
      pmSysBoot(false);
      __SEV();
      __WFE(); // go to sleep until interrupt wakes
      __WFE(); 
    }
   }
  } 
NOTE: pm functions need to be redefined from 'static' and listed in pm.h to access from main.c

For completeness here is the timer init and IRQ for the curious people who might want them :D

Code: Select all

void TIMER0_IRQHandler() {
  boot_flag = !boot_flag;
  NRF_TIMER0->EVENTS_COMPARE[0] = 0;

  //if (boot_flag == true) {LED_ON();}
  //if (boot_flag == false) {LED_OFF();}
}

void timer0_init(uint32_t millisecond_sleep) {

  NRF_TIMER0->TASKS_CLEAR = 1;

  NRF_TIMER0->PRESCALER = 4;
  NRF_TIMER0->CC[0] = millisecond_sleep*1000; // if millisecond_sleep is 1000 it sleeps for 1 second
  NRF_TIMER0->INTENSET = TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos;  // taken from Nordic dev zone
  NRF_TIMER0->SHORTS = (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos);
  NVIC_SetPriority(TIMER0_IRQn, 3);
  NVIC_EnableIRQ(TIMER0_IRQn);

  NRF_TIMER0->TASKS_START = 1;

  boot_flag = false; // set global boot flag
} 

Re: Power Consumption

Posted: Tue Dec 06, 2016 9:21 pm
by arnaud
One of the pin from nRF51 to STM32 is used to indicate if the stm should be started in firmware mode or in bootloader mode, this pin should be set to the right level before releasing the STM32 reset but after powering VCC. It looks like you are booting the STM in bootloader mode (with pmSysBootloader(true)). That could be the reason you are not seing the stm32 starting, it starts but not in firmware mode. You should also call the pmSysBoot() function to set the bootloader pin.

You can try this sequence to power the system:

Code: Select all

      pmPowerSystem(true);
      pmSysBootloader(false);
      pmSysBoot(true);
      pmRunSystem(true);
And the oposite to turn it off:

Code: Select all

      pmRunSystem(false);    
      pmSysBoot(false); 
      pmPowerSystem(false);

Re: Power Consumption

Posted: Wed Dec 07, 2016 11:59 am
by kekeller
Still not working. It's still starting VCC but the STM never actually boots.

I also tried directly booting in main without the sleep mode and the timer. It works but it takes about 12 seconds from the LEDs turning on to the system actually booting when the motors test themselves.

Code: Select all

int main()
{
  pmPowerSystem(true);
  pmSysBootloader(false);
  pmSysBoot(true);
  pmRunSystem(true);
  
  while(1){} 
}
I tried also adding small delays between each step.
for(i=0;i<255;i++)
I thought perhaps it was a rise and fall timing issue on the pins but that made no difference.

1. Directly booting in main works but takes 12 seconds
2. Booting in while loop based on a flag set every 15 seconds does nothing except turn VCC on.
3. I added pmInit(); to the initialization with no change.

Any other ideas? It's so strange that the STM can't be directly booted from the NRF.

Re: Power Consumption

Posted: Wed Dec 07, 2016 7:58 pm
by arnaud
It is indeed very strange: the STM32 is booted from the nRF in the stock firmware. The nRF is always ON and boots the STM32 then the button is pressed.

Do you have a SWD programmer? You can try to flash an STM32 firmware compiled with "CLOAD=0" in config.mk. This will allow to rule-out the possibility that this is a bootloader boot problem: it will erase the bootloader and directly boot the firmware as soon as reset is released.

/Arnaud