PDA

View Full Version : PIC18F13K50, CDC USB communication and ultra-low power temperature logger



aberco
- 23rd August 2010, 02:42
Dear everyone!

I am in the process of starting a new project around the 18F13K50, which have to mix ultra-low power and USB communication, a combination that seems to be difficult to mix.

I had previous success (about 3 years ago) with a couple of very simple project around the 18F2550/4550 and CDC communication profile. But now it seems that there is much more new things added to USB coding, including new USB handling library, and of course new USB pics from microchip too! The PIC18F13K50/14K50 is now becoming an exciting candidate for very small USB projects, and after upgrading MPLAB, purchasing a PicKit 3 and trying to makes everything working back together I can now concentrate on writing code!

Now onto the project, it is a temperature logger that will sample temperature at a preset interval of time and store it in EEPROM. Content of the EEPROM can then be uploaded to a computer using the CDC USB profile. This is actually very similar in conception to jellish00 ultrasonic logger project that was discussed a bit in this post (http://www.picbasic.co.uk/forum/showthread.php?t=5418&p=80414#post80414).

Temperature logger in standalone mode
Now the challenge is to run the device out of an ultra-small 25mAh LiPO battery. That is not a whole lot of juice, but using power conservation technique I hope to be able to run it for a long period of time (namely, a few months).

The hardware that will actually eat power on the device:
- 3,3V Voltage regulator, TPS72933, quiescent current 500nA.
- I2C EEPROM, quiescent current about 1µA, 5mA when writing.
- I2C Temperature sensor TMP100, quiescent current about 1µA, 70µA when sampling.
- A bicolor LED, for indicating errors (battery low, memory full). This will not be normally used.
- The PIC, which is going to be the biggest battery drain.

Here's my idea for power-saving for the PIC. Ideally a timer with the crystal used as a clock source (for accuracy) would be used to define my sampling interval (ideally 1sec, or 5sec). this would send an interrupt to the PIC, getting it out of sleep mode. It would then increment a counter (to get to longer sampling intervals), and when needed, trigger a temp sample on the TMP100 and store it to EEPROM. Then going back to sleep till next timer interrupt.

The USB charger is also connected to INT0 to send an interrupt when the USB power is connected.

The battery voltage level is also measured with the PIC ADC, but can be polled with temperature.

While the timer is ran on the external crystal oscillator, the PIC core may have to be run on the LF internal oscillator (31kHz), providing the lower consumption. The operation in standalone mode is actually not very challenging, what is more is to do it with little power!

Temperature logger in USB mode
In USB mode the logger will charge its battery over the USB current. I will have to wake the USB module oscillator, and very likely to change the core frequency to a much faster pace in order to send the data rapidly. The complicated part is all the USB code to handle the CDC communication, and I don't see myself writing that in C or assembler!

While I understood that the PIC can support all this in hardware, I am not sure about the capability yo implement it all in PicBasic, at least without using ASM calls. DEFINE OSC can only be used once, making a change in OSC frequency difficult for all PAUSE and delays used in the program. DEFINE OSC cannot accommodate for anything lower than 3.58MHz too. Hardware interrupt are not very obvious to handle in PicBasic, though I just found out the library written by Darrel Taylor (http://darreltaylor.com/DT_INTS-18/downloads.html) which looks very promising. I have yet to dig in the details for using it.


Here is the quick and dirty prototype... at least the hardware works nicely!

http://aberco.free.fr/imagesdivers/logger1.jpg

Of course there's extra things too, the LCD is actually quite handy for debuging ;)
Here it is polling temperature from the TMP100 in "one shot" sample mode, displaying it as the raw 12bit data + converted value (Yes it is hot in Paris tonight!).

Any consideration on the feasibility of such project with PicBasic?

I will probably have more question that will arise while advancing in the programming...

Looking forward to discuss around this!

rsocor01
- 23rd August 2010, 20:43
Here it is polling temperature from the TMP100 in "one shot" sample mode, displaying it as the raw 12bit data + converted value (Yes it is hot in Paris tonight!)

Ooh, I love your city. I'm turning red now...:o

Well, that's a lot of info in one post. I think your project can be done in PBP with no problem. The part that I think is unrealistic is trying to get this device running for a few months with a 25mAh LiPO battery. Let's say that the average comsumed current of your device is 1mA, then with some luck you can run your device for 25 hours. You are taking into consideration only the quiescent currents, but what about the operating currents?

Is this device going to be connected to the USB port all the time? Can you use a bigger battery?

Robert

aberco
- 24th August 2010, 00:28
Hi Bob! thanks for your observations!

Indeed, 1mA is waaaay too much!!!

I am giving the quiescent current because this is what is consumed most of the time. The component will be turned on when sampling for a couple ms, a couple of time a day.

Without counting the PIC, I have at most 3µA of current IDLE, and 5mA at most when writing to EEPROM. To simplify calculation let's say we use the sampling routine for 1 second every hour (that's likely to be longer than needed). So, for hourly consumption that gives: (1*5/3600)+(0.003*3599/3600) = 4,38 µAh
That's about 190 days on 20mAh.

I have already all conservation routines programmed and tested for the peripherals, so I'm confident that these numbers are meaningful. I measured them on my prototype.

Now comes the PIC! The solution would be to shut off the CPU core between sampling and use interrupt from the timer to wake it up. Peripherals and timers can work on their own, and this would cut down the PIC consumption to a few µA too.


Now the device itself will be build inside the body of an USB jumpdrive. It will not be connected to USB when sampling, so there's no available power. The limited amount of space within the jumpdrive body does not allows for much options as well. I have found the smallest LiPO battery, the 25mAh model, that can fit within 1 by 2cm space in the back of the enclosure. They have a 60mAh model too, but it is significantly larger, and I need to keep some space to cram SMD components on the PCB too. So, Is this device going to be connected to the USB port all the time? No, and Can you use a bigger battery? If I really have to that will be the option. However I first need to design the device to be the most power efficient, regardless of available battery capacity.

I'll go through a step by step testing of these power saving possibilities with PicBasic... hopefully without ASM calls!

aberco
- 24th August 2010, 02:19
Trying to get the USB com. working.
Now there's a little details that I have seen stated but not previously understood:

The 18F13K50/14K50 requires the use of an external crystal of 12 or 48 Mhz ONLY! The internal clock circuitry is in fact simpler than what the 2550/4550 has, and the only option to feed the USB oscillator is either directly or using a x4 PLL. CPU frequency can then be derived from the PLL using ÷1, 2, 3 or 4.

No problem for my USB mode, but for my low power mode running at 12Mhz is out of question. That will require the use of the internal RC oscillator, and a loss of timing precision between the temperature samples (which is not overly critical).

An other solution is to use the second external oscillator and wire a 32,768kHz crystal to it (with a bit more PCB real estate used).

rsocor01
- 24th August 2010, 03:08
Check this thread out.

http://www.picbasic.co.uk/forum/showthread.php?t=13560

aberco
- 25th August 2010, 02:54
Cool! I missed this thread, I'll dissect it carefully, looks pretty much like all I want!

aberco
- 27th August 2010, 03:35
Back on the PIC, dissecting the datasheet, this is what I have for the LF13K50

• Sleep mode: 24 nA
• Watchdog Timer: 450 nA
• Timer1 Oscillator: 790 nA @ 32 kHz

So using the watchdog timer to wake up the pic should lead to extremely low power consumption, provided that I don't need to wake the pic often, and that it won't do much when it'll be awake (turning back to sleep rapidly).

I could even experiment the use of timer1 driven by the 32k crystal instead of the watchdog to give much more decent time accuracy on my measurements intervals.

My power rail is 3.3V so I can use the LF model. I could reduce even more consumption by lower it down to 2.8V using another regulator. 2.5V or 1.8V would be even better, but then the temperature sensor TMP100 is off specs (2.7V min).

Looks good on the paper, now onto the program to get this. I still need to fix the USB side first though...

aberco
- 30th August 2010, 13:03
I could not get the CDC demo to run on my 18F4550 board, (though, 3 years ago it was running fine... but since then I changed PBP, MCS and PMLAB versions...). I preferred to carry on the actual programming of the project. Getting almost done, now with automatic EEPROM identification and temperature logging.

http://aberco.free.fr/imagesdivers/tempsmall.jpg

Just have to improve power consumption and add USB com.

rsocor01
- 31st August 2010, 05:03
Looks good on the paper, now onto the program to get this. I still need to fix the USB side first though...

Aberco,

It would be interesting to see a Battery vs. Time plot after you are done with your design to see how well the battery is holding on.

Robert

aberco
- 2nd September 2010, 00:33
Yep will do!
I have setup the secondary oscillator with a 32k XTal. That way it will give me the time accuracy I need and I can clock the CPU using that source. I have yet to finish the main routine and get everything to work before implementing the power conservation tricks.... and that USB communication deal to figure out.

aberco
- 4th October 2010, 18:27
It was time to pack things down, I must say that it is not easy to drill vias using a 0.3mm drillbit and sticking a tiny copper wire in it to make the connexion!

http://aberco.free.fr/imagesdivers/protologger.jpg

Not much progress on the programming yet due to lack of free time, but will work on that soon.

aberco
- 27th October 2010, 21:24
Back with more news, I made some great progress with the programming!

I am trying to implement the low power mode, however I find microchip datasheet to be a bit confusing. I switch from a 48Mhz CPU clocked from 12MHz HS primary oscillator + PLL to the Timer1 clock source (SEC_RUN mode) when entering low power operation:



'Oscillator software configuration for 32.768kHz operation on Timer1 clock
OSCCON.1 = 0
OSCCON.0 = 1 'Use Timer1 oscillator as clock source
OSCTUNE.6 = 0 'Disable PLL
OSCCON2.2 = 0 'Disable primary oscillator
OSCCON.7 = 1 'Device enters in IDLE mode when sleep instruction issued


Then I have my main standalone operation loop. The only code executing are triggered by INT0 and TMR1 using DT_INTS-18.



StandAloneLoop:

@ SLEEP

GOTO StandAloneLoop


It does work well if the operating mode is IDLE (IDLEN = 1). This mode turn off CPU clock but leave all peripheral clocked (here, from Timer1 source). I tried this instead:



OSCCON.7 = 0 'Device enters in SLEEP mode when sleep instruction issued


This would allows to save even more by turning off the peripheral too, however the first interruption does work, and after the PIC doesn't wake up anymore. In the datasheet it says
This shuts down the selected oscillator and all clock source status bits are cleared.
However the only peripheral that needs to run is the Timer1 to trigger the interrupt, but that can only happen if the secondary oscillator is running. If there's no way to use SLEEP mode while keeping the secondary oscillator running, then I should probably use the SEC_IDLE mode... hopefully the peripherals don't drain that much power.

Darrel Taylor
- 27th October 2010, 21:49
If you put a crystal on the Timer1 oscillator, enable T1OSCEN and change TMR1CS before going to sleep with an appropriate reload value for the lower frequency ... you could put it to sleep.

aberco
- 28th October 2010, 00:07
Hmm I don't really understand, I have this at the beginning of my code during initialization:


T1CON = %01101011 'Set Timer prescaler to /4 and enable Timer1 on external 32768Hz crystal

T1OSCEN = 1 (secondary 32768Hz oscillator is enabled)
TMR1CS = 1 (timer clock source is secondary 32768Hz oscillator)

My setup already use the Timer1 for both interrupt and general clock source when in low power mode, and it does work as expected.

I tried to add that T1CON configuration line above my @ SLEEP instruction but that didn't help much. If the SLEEP mode actually turn off all clocking sources then T1OSCEN bit should be set to 0 as well.

Maybe using the IDLE mode and manually disable all peripherals that are enabled default would be a workaround.

Darrel Taylor
- 28th October 2010, 02:49
Timer1 oscillator continues to run during sleep mode, but ... try it like this.
First, comment all the OSCCON and OSCTUNE statements you showed above.

Then ...

StandAloneLoop:
ASM
SLEEP
NOP
NOP
ENDASM
GOTO StandAloneLoop

aberco
- 28th October 2010, 18:39
Tried this step by step.

Commenting either or all of these:



OSCCON.1 = 0
OSCCON.0 = 1 'Use Timer1 oscillator as clock source
OSCCON.7 = 1 'Device enters in IDLE mode when sleep instruction issued

stop operation. However I'm not sure if it's because the interrupt is not triggered anymore or if that's because the CPU does not come back from sleep. I remember reading that Timer1 oscillator was always running, but looking carefully at the datasheet again I cannot find that statement back. Only mention is that SLEEP (not IDLE) mode turn off all clocks and all oscillators, expect for the WDT oscillator (if enabled).

Darrel Taylor
- 28th October 2010, 19:38
<img src="http://www.picbasic.co.uk/forum/attachment.php?attachmentid=4887" />

And you had more statements than those 3.
One of them disables the Primary Oscillator, which will keep it from running after it wakes up I would assume.

aberco
- 28th October 2010, 20:25
Yes but I commented all others as well. I just quoted the lines that caused the interrupt to stop working.

I want to disable the primary oscillator, because I have 2 operating modes:

1) USB attached, clocked from a 12Mhz ceramic resonator, with PLL enabled and CPU clocked at 48Mhz

2) USB detached, standalone, CPU and peripherial clocked from Timer1 secondary oscillator.

When the CPU wakes from sleep it should resume on the oscillator defined by the SCS bits, here SEC_RUN mode:


OSCCON.1 = 0
OSCCON.0 = 1 'Use Timer1 oscillator as clock source


Now you found that statement back from the datasheet, there's hope to make it work! I'll investigate harder and make some tests on a simplified program.

aberco
- 29th October 2010, 13:38
I realized that I have a very strange problem when I write to my I2C EEPROM when the CPU is clocked at 32.768kHz, I get corrupted data if there's a long chain of "0" being sent.

I record my temperature samples two by two, and they span 3 bytes in memory (Byte A, B and C). One sample is 12bit, 8 bit for integer value (Sign + 7 bit value), and 4 bits for decimal value (0.0625 steps). They are recoded with an interleave routine as such:

Sample 1 : AAAAAAAA.BBBB
Sample 2 : BBBBCCCC.CCCC



1811 2010/10/29 0h44m00s +23.9375
1812 2010/10/29 0h44m10s +23.9375

1813 2010/10/29 0h44m20s +24.0000
1814 2010/10/29 0h44m30s -7.9375

1815 2010/10/29 0h44m40s +24.0000
1816 2010/10/29 0h44m50s -7.9375

1817 2010/10/29 0h45m00s +24.0000
1818 2010/10/29 0h45m10s -8.0000

1819 2010/10/29 0h45m20s +23.9375
1820 2010/10/29 0h45m30s +23.9375


I have a 5ms pause between the 3 write operations, and there's about 20 sec between the record of each packets of 3 bytes. I tried increasing the write delay to 20ms without changes, and EEPROM VCC is within range.

This occurs when odd samples ends with .0000, .2500, .5000, and .7500, the problem does not appears if I run the CPU using the internal oscillator at 250kHz (and readjusting all the delay values accordingly), which makes me wonder if I2CWRITE can be used with a CPU clock of 32.768kHz...

Also, this might be related to the issue I have... is doing such operation:

DataValue = TempH >> 4

modify the original value of TempH?

aberco
- 8th November 2010, 21:15
The logger project is getting near completion! I am now into the autonomous mode power, and I was able to measure these figures while powering the device from a battery across a 10 ohm shunt.

http://aberco.free.fr/imagesdivers/loggerpower.JPG

It is quite clear that I have to improve power consumption as at 900µA the 130mAh battery runs for about 6 days... The PIC sits most of the time at IDLE, and here it shows where a second sample is read and written to memory with the first previously read sample (hence the 3 write cycles for 2x 12bits).

I have not managed yet to make the true sleep mode to work, but at IDLE the power consumption seems to be very high... there's no difference than when running the CPU from internal clock at 250kHz. As I said above I tried running the CPU from Timer1 oscillator but that gave me some memory writing issue so I quitted.

Other than the PIC eating power I have (when IDLE):
LDO regulator, 500nA
I2C EEPROM, 1µA
I2C Temperature sensor, 1µA
220k/220k voltage divider, 5µA

Will try to investigate more and post results :)

Ioannis
- 8th November 2010, 21:32
Maybe you can control EEPROM and Temp. Sensor power by a pin from your controller. When you have to make new measurements, just make the pin high, wait a little to let the circuit settle, and do your sampling and writing. Then switch them off again.

Ioannis

aberco
- 8th November 2010, 21:37
Design is completed and can't be changed, beside there's no available I/O pin left.

IDLE power consumption is actually from the PIC and not from the peripherals.

pedja089
- 8th November 2010, 23:26
I managed to reduce consumption to less than 50uA.
Here (http://www.picbasic.co.uk/forum/showthread.php?t=13837) is main part of the code.

aberco
- 8th November 2010, 23:33
That would be pretty good! I will have a look at how you managed to get that and will let you know. Thanks for the help!

aberco
- 9th November 2010, 00:35
Took me too long to edit the previous post, I got locked!

I have downloaded the XLP LowPower App note from microchip and it is helpful. The 14K50 does not allows for deep sleep, but regular sleep should do.

Obviously IDLE mode consumes 25% less than the normal run power, so I will have to make the Sleep mode to work while getting the PIC to resume from it. However there's probably something else that I have to find out, as 900µA seems to be abnormal for IDLE at 250kHz... I'll have to double check if the peripherals are also turning into low power too. I have also reduced the power supply to 2.2V (the regulator is able to switch from 3.3V for USB operation to 2.2V - TPS780330220 from TI). that should help a bit with consumption.

Could the I2C pullup be a problem? I have used 6.8k resistors which is pretty much the maximum, at 10k and beyond the operation of the I2C bus is unstable.

Ioannis
- 9th November 2010, 07:32
If the two resistors are grounded, then the current through them, is close to 900uA.

Make sure the pins that these are connected, are set to high or z-state before sleep.

Ioannis

tron235
- 4th November 2011, 18:21
Anyone know if this is still an active item PIC18F13K50T-I/SO (http://www.http://netsemi.com/p-2333367-mcu-8-bit-pic18-pic-risc-8kb-flash-33v5v-20-pin-soic-w-tr.aspx)

rmteo
- 4th November 2011, 18:44
Anyone know if this is still an active item PIC18F13K50T-I/SO (http://www.http://netsemi.com/p-2333367-mcu-8-bit-pic18-pic-risc-8kb-flash-33v5v-20-pin-soic-w-tr.aspx)

Did you check at MCHP's website http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en533925