Arm Community
Arm Community
  • Site
  • User
  • Site
  • Search
  • User
Arm Community blogs
Arm Community blogs
Embedded and Microcontrollers blog Batteryless Energy Harvesting Remote Control Power Regulation With The ARM Cortex-M0+
  • Blogs
  • Mentions
  • Sub-Groups
  • Tags
  • Jump...
  • Cancel
More blogs in Arm Community blogs
  • AI blog

  • Announcements

  • Architectures and Processors blog

  • Automotive blog

  • Embedded and Microcontrollers blog

  • Internet of Things (IoT) blog

  • Laptops and Desktops blog

  • Mobile, Graphics, and Gaming blog

  • Operating Systems blog

  • Servers and Cloud Computing blog

  • SoC Design and Simulation blog

  • Tools, Software and IDEs blog

Tags
  • energy-harvesting
  • remote-control
  • Cortex-M0+
  • power-management
Actions
  • RSS
  • More
  • Cancel
Related blog posts
Related forum threads

Batteryless Energy Harvesting Remote Control Power Regulation With The ARM Cortex-M0+

Elliott Smith
Elliott Smith
December 2, 2013

This post is concerned with the techniques used to harvest and regulate energy for the Energy Harvesting Remote Control.

Sources of Energy Harvested:

The main source of energy harvested in the remote control is solar power. The idea here was that you could leave the remote control to charge up during the day and then when you came to use it at night it would have a sufficient amount of charge for a night of usage. The remote control also features a coil and magnet. This was included to harvest some extra energy, from movement, during use. Both of these sources of energy are used to charge up a 5 Volt, 3 Farad Super Capacitor. The Super Capacitor has a Zener Diode protection circuit to prevent overcharging.

Capture.PNG

Power Management:

The super capacitor is used to power a 2.5 volt voltage reference with a quiescent current of 50uA. It is capable of supplying up to 25 mA. This reference can thus power the remote control most of the time. The exception is if an IR code is being sent, or the e-ink screen needs updating.

Capture1.PNG

When IR codes are being sent, or the e-ink screen needs updating, a buck-boost converter is used to buck or boost the voltage accordingly. A 22uH inductor was used to achieve 3 volts from a 2.7-5 volt range.

Capture2.PNG

The buck boost power is enabled using an output pin on the MCU and the following circuit:

Capture3.PNG

A switching speed of about 2MHz was used for the buck-boost PWM pins. The output voltage is controlled by the duty cycle of the switch frequency. The 16-bit counters on the MkLl25Z PWM module provide a lot of control over the output voltage. The setup code for the power management is shown below:

/*------------------------------------------------------------------------------
  Set up and configure the buck boost regulator to start. ADC set up to interupt
    if the output voltage is not within set limits
 *------------------------------------------------------------------------------*/
char start_buckboost(void)
{
    unsigned short adc_read;
    short PWM0,PWM1;
    SIM->SCGC5 |= (1UL << 13) | (1UL << 9);

    //BB PWM0
    PORTE->PCR[22] = (0x3 <<  8);    
    FPTE->PDDR |= (1UL <<  22);

    //BB PWM1
    PORTE->PCR[23] = (0x3 <<  8);    
    FPTE->PDDR |= (1UL <<  23);

    //BB Enable
    PORTA->PCR[12] = (0x1 << 8);
     FPTA->PDDR |= (1UL << 12);

/*------------------INSERTED TO FIX VREF PROBLEM----------------------*/
    ADC_configure();
    ADC0->CFG2 |= (1UL << 4); // READ ADC ADC_SExb 
    adc_read = ADC_readVal(6);
    TPM_enable(2);
    TPM2->MOD = 0xFF;




The ADC is used to set the PWM for the buck-boost converter. The reference voltage generator provides a reference voltage for the ADC to compare against. The input to the ADC is made using a potential divider to halve the voltage. This ensures that the voltage going into the ADC is always less than the reference voltage.  The code below shows some of the duty cycles being set to buck the buck boost converter.

    //4.8-5 V Buck
    if((adc_read <= 0xAD00) && (adc_read > 0xA500))
    {
            TPM_configure(2,0,((0x1<<2)|(0x1<<5)), 0x090);
            TPM_configure(2,1,((0x1<<2)|(0x1<<5)), 0x100);
    }

    //4.5-4.8 V Buck
  else if((adc_read <= 0xA500) && (adc_read > 0xA0E5))
    {
            TPM_configure(2,0,((0x1<<2)|(0x1<<5)), 0x0A5);
            TPM_configure(2,1,((0x1<<2)|(0x1<<5)), 0x100);
    }

    //4.1-4.5 V Buck
    else if((adc_read <= 0xA0E5) && (adc_read > 0x9400))
    {
            TPM_configure(2,0,((0x1<<2)|(0x1<<5)), 0x0B9);
            TPM_configure(2,1,((0x1<<2)|(0x1<<5)), 0x100);
    }
    //3.8-4 V Buck
    else if((adc_read <= 0x9400) && (adc_read > 0x88E4))
    {
            TPM_configure(2,0,((0x1<<2)|(0x1<<5)), 0x0CA);
            TPM_configure(2,1,((0x1<<2)|(0x1<<5)), 0x100);
    }
    //3.6-3.7 V Buck
    else if((adc_read <= 0x88E4) && (adc_read > 0x7F00))
    {
            TPM_configure(2,0,((0x1<<2)|(0x1<<5)), 0x0D9);
            TPM_configure(2,1,((0x1<<2)|(0x1<<5)), 0x100);
    }
    //3.5 V Buck
    else if((adc_read <= 0x7F00) && (adc_read > 0x7E00))
    {
            TPM_configure(2,0,((0x1<<2)|(0x1<<5)), 0x0DB);
            TPM_configure(2,1,((0x1<<2)|(0x1<<5)), 0x100);
    }
    //3.4 V Buck
    else if((adc_read <= 0x7E00) && (adc_read > 0x78D6))
    {
            TPM_configure(2,0,((0x1<<2)|(0x1<<5)), 0x0E0);
            TPM_configure(2,1,((0x1<<2)|(0x1<<5)), 0x100);
    }
    //3.3V Buck
    else if((adc_read <= 0x78D6) && (adc_read > 0x7650))
    {
            TPM_configure(2,0,((0x1<<2)|(0x1<<5)), 0x0F0);
            TPM_configure(2,1,((0x1<<2)|(0x1<<5)), 0x100);
    }
    //3.2V Buck
    else if((adc_read <= 0x7650) && (adc_read > 0x7200))
    {
            TPM_configure(2,0,((0x1<<2)|(0x1<<5)), 0x0F9);
            TPM_configure(2,1,((0x1<<2)|(0x1<<5)), 0x100);
    }
    //3.1V Buck
    else if((adc_read <= 0x7200) && (adc_read > 0x6F00))
    {
            TPM_configure(2,0,((0x1<<2)|(0x1<<5)), 0x0FF);
            TPM_configure(2,1,((0x1<<2)|(0x1<<5)), 0x100);
    }
    //3V Stay the same
    else if((adc_read <= 0x6F00) && (adc_read > 0x68F3))
    {
            TPM_configure(2,0,((0x1<<2)|(0x1<<5)), 0x100);
            TPM_configure(2,1,((0x1<<2)|(0x1<<5)), 0x0F0);
    }
    //2.9 Volt boost
    else if((adc_read <= 0x68F3) && (adc_read > 0x66DF))
    {
            TPM_configure(2,0,((0x1<<2)|(0x1<<5)), 0x100);
            TPM_configure(2,1,((0x1<<2)|(0x1<<5)), 0x0D5);
    }
    //2.8 Volt boost
    else if((adc_read <= 0x66DF) && (adc_read > 0x6473))
    {
            TPM_configure(2,0,((0x1<<2)|(0x1<<5)), 0x100);
            TPM_configure(2,1,((0x1<<2)|(0x1<<5)), 0x0A5);
    }
    //2.7 Volt Boost
    else if((adc_read <= 0x6473) && (adc_read > 0x5FE0))
    {
            TPM_configure(2,0,((0x1<<2)|(0x1<<5)), 0x100);
            TPM_configure(2,1,((0x1<<2)|(0x1<<5)), 0x0A0);
    }
    else
    {
            return 0;
    }


    TPM_start(2);
     FPTA->PDOR |= (1UL << 12);
    return 1;




This solution for power management is elegant and allows the MCU to do most of the power management. As a result, we were able to save power here when compared with other power management solutions.

The next development step was Utilising The LLS Mode And The LLWU For The Kl25z Series

Anonymous
Embedded and Microcontrollers blog
  • Adapting Kubernetes for high-performance IoT Edge deployments

    Alexandre Peixoto Ferreira
    Alexandre Peixoto Ferreira
    In this blog post, we address heterogeneity in IoT edge deployments using Kubernetes.
    • August 21, 2024
  • Evolving Edge Computing and Harnessing Heterogeneity

    Alexandre Peixoto Ferreira
    Alexandre Peixoto Ferreira
    This blog post identifies heterogeneity as an opportunity to create better edge computing systems.
    • August 21, 2024
  • Demonstrating a Hybrid Runtime for Containerized Applications in High-Performance IoT Edge

    Chris Adeniyi-Jones
    Chris Adeniyi-Jones
    In this blog post, we show how a hybrid runtime and k3s can be used to deploy an application onto an edge platform that includes an embedded processor.
    • August 21, 2024