Pushing the limits of a PIC10F222


Closed Thread
Results 1 to 6 of 6
  1. #1
    Join Date
    Nov 2006
    Posts
    70

    Default Pushing the limits of a PIC10F222

    I am working on some tiny dataloggers--these things weigh less than a raisin--and I have had great success with several PICs (12Fs and 16F688). To miniaturize things even more, I've been trying to use a PIC10F222, but I fear there just is not enough code space. I have written some code that might work (I have tested all the components of code) but I am short about 100 words or so when I put it all together. I am contemplating dealving into assembly to save some space, but I wonder if the PIC10 data logger will work even then. I am hoping that if I post my code here, some of you could give it a glance and suggest some shortcuts and/or give me some insight as to whether using assembly could make this project possible.

    The device is pretty simple. It interfaces with an external EEPROM (Microchip 24AA256) and a Clock via I2C. The clock is set to emit an 'alarm' every minute which wakes the PIC from sleep. Once awake the PIC accesses the EEPROM to obtain some stored parameters (the PIC cannot retain variable in sleep mode, and sleep is absolutely necessary), does an ADC conversion from the sensor, and then stores the data in the EEPROM. Every tenth minute, an average ADC value is calculated from the sum of the 10 previous ADC operations. So every datapoint in the permanent EEPROM storage is an average over 10 minutes. More details are in comments within the code. One of the main problems is that the I2CREAD command is huge. It takes up about 150 words. Perhaps there is an assembly (or even a PBP) solution that is more efficient. I hope some of you have some suggestions. Thanks.

    Code:
    'This program runs the PIC10f222 on a tiny geolocator module.
    'The device makes an ADC reading once a minute. Every 10 minutes, when the
        'minutes value ends with a 9, it stores an average of the last 10 ADC
        'values to the MICROCHIP 24AA256 EEPROM. ADC values are 7 bits 
     '(range 0 to 127)
    'The device should not log data at certain times (middle of day and middle
     'of night). Logging is controlled by IF/THEN statements dependent on 
     'the minute counter.
    '
    'PARAMETER STORAGE: 
    'ADC SUM (max value 1270) in EEPROM BYTES 31982 and 4 high bits of 32983             
    'Minute counter (max value 1440) stored in EEPROM BYTES 31984 and 
     '4 low bits of 32983
    'MEM address (max ~32000) in EEPROM BYTES 31985-31986
    'the initital start time is stored in EEPROM BYTES 31987 to 31992.
    'Memory testing EEPROM BYTE 31993
    'No date skipping
    '
    'DATA STORAGE
    'first EEPROM memory address for data storage is 0. Last address is 31980
    '_________________________________________________
    '
    DEFINE ADC_SAMPLEUS 100  'Sampling time for ADC
    DEFINE I2C_SCL GPIO,2
    DEFINE I2C_SDA GPIO,0
    '
    'Alias pins          
    INT     VAR GPIO.3 'interupt (wake-up) pin (pin 6, input only)
    SDA     VAR GPIO.0 'I2C DATA PIN (pin 1),               
    SCL     VAR GPIO.2 'I2C CLOCK PIN (pin 4)
    LIGHT   Var GPIO.1 'INPUT FROM LIGHT SENSOR (pin 3)
    ' 
    'Need 6 byte variables, Soft stack set to 1 byte, RR1 and RM1 
    'commented out in RAM file
    B0 VAR Byte[6] '6 byte array
    '
    'Word names aliased to Bytes using EXT
    ASM
     W0 = _B0 + 0
     W1 = _B0 + 2
     W2 = _B0 + 4
    ENDASM
    W0 VAR WORD EXT
    W1 VAR WORD EXT
    W2 VAR Word EXT
    '
    wake: 'The action starts here
    OPTION_REG = %00000000
    TRISIO = 0 'all outputs 
    OSCCAL.0 = 0 'must be set to zero on wake-up
    ADCON0 = %00000000
    '
    IF INT = 1 tHEN 'Detects data collector
     PAUSE 100 
        GOTO nolog 'loops until data collector is unplugged
    ENDIF
    '
    W2 = 32981 'Set memory address to collect stored parameters
    GOSUB readmem  'RETURNS ADC SUM, COUNTER, and EEPROM Memory address
    IF W2 = 31980 Then nolog 'Stops logging when memory is full
    B0[0] = B0[2]//4 'Makes W0 the ADC SUM
    B0[2] = B0[2]//16 ' Makes W1 the COUNTER
    IF W1 < 180 THEN nolog 'no logging before counter = 180
    IF W1 > 599 THEN 'no logging between 600 and 899
     IF W1 < 900 THEN nolog
    ENDIF
    IF W1 > 1379 THEN nolog ' no logging after counter is 1380
    OPTION_REG = (W1//9) 'store ones digit of counter in OPTION_REG 
    IF W1 = 909 THEN 'First logging after aftenoon sleep is at counter 909
     FSR.0 = 1 'Use FSR to flag this situation
    ELSE 
     FSR.0 = 0
    ENDIF 
    '
    ADCIN 1, B0[2] 'perform ADC on channel 1 (GPIO 1) and stores in B2 or W1.Byte1
    B0[2] = B0[2] / 2 'divide by 2
    W0 = W0 + B0[2] 'add to ADC sum
    '
    IF OPTION_REG <> 0 THEN nolog 'log data only every 10 minutes 
     '(when ones digit of counter = 9)
    B0[1] = W0 / 10 'Calculates ADC average
    B0.0[15] = FSR.0 'flag bit 7 of B0[1] if waking from afternoon sleep. 
    '_____________________________________ 
     'at this point:
      'B0[0] = 1 
      'B0[1] = ADC Average
      'W1 = junk
      'W2 still equals EEPROM memory address
    '________________________________________
    GOSUB writemem 'Write only B0[1]
    PAUSE 5
    W2 = 32981
    GOSUB readmem
    W0 = 0 'clear ADC sum
    B0[2] = B0[2]//16 'clear four high bits from B0[2] (calculate count as W1)
    '
    nolog:
    W1 = W1 + 1 'add 1 to minute COUNTER
    IF W1 = 1440 then W1 = 0 'reset minute count if necessary
    'ROUTINE TO STORE PARAMETERS
    '_____________________________________ 
     'at this point:
      'W0 = ADC SUM
      'W1 = current Counter
      'W2 = memory address
    '________________________________________
    'Repackage ADC SUM and Counter to free up B0[0]
    B0[0] = B0[0] << 4 'shift bits of B0[0] over to high side
    B0[2] = B0[2] + B0[0] 'add shifted bits of B0[0] to B0[2]
    W2 = 32981
    GOSUB writemem
    '
    ADCON0 = %11001100 'must be in this state for some reason
    OPTION_REG = %01000000 'SET OPTION REGISTER FOR WAKE ON CHANGE
    TRISIO = %00001111 'wake ups on GP3 and GP0
    'PAUSE 2000
    'GOTO wake
    B0[0] = GPIO 'read pins to establish change state.
    '....and go to sleep.
    @ SLEEP
    '
    'SUBROUTINES
    '
    readmem:
    I2CREAD SDA,SCL,$A0,W2,[W0,W1,W2]
    RETURN
    '
    writemem:
    B0[0] = 1 'set initial B0[0] value
    writeagain:
    I2CWRITE SDA,SCL,$A0,W2,[B0[B0[0]]] 'write byte designated by B0[0]
    IF W2 < 31981 THEN RETURN
    IF B0[0] = 3 THEN RETURN
    B0[0] = B0[0] + 1
    W2 = W2 + 1
    GOTO writeagain
    end

  2. #2
    Join Date
    Sep 2007
    Location
    USA, CA
    Posts
    271


    Did you find this post helpful? Yes | No

    Default

    With care, there's no reason you can't get it to work.

    The Pause command could be a rom hog for what you're doing with it; you'll save some space by using simple loops, setting a variable before the gosub. You might also try polling the eeprom; that's not too difficult if it has it. (Read the eeprom datasheet.) On one I used a while back, I sent it a command until I got an ack back, then canceled the command. The loop for that is pretty short, but it depends on the particular eeprom you are using.

    Another thing to watch out for is the program counter. I worked with some little pics a couple years ago (10f or 12f-- can't remember), and they didn't allow gosubs or goto's beyond the first 256 program words. Check the pic datasheet to make sure the program counter in your pic allows the "long" jumps.

  3. #3


    Did you find this post helpful? Yes | No

    Default RAM preserved in sleep

    You say "(the PIC cannot retain variable in sleep mode, and sleep is absolutely necessary)" but what do you base this on? I have skimmed the data sheet and I am led to believe that RAM IS preserved.

    Table 10.1 on page 53 says that data will be preserved as long as the supply voltage stays above 1.5 volts.
    Parameter D002 VDR RAM Data Retention Voltage(2) — 1.5* — V Device in Sleep mode
    Note 2: This is the limit to which VDD can be lowered in Sleep mode without losing RAM data.

    What I would be checking is voltage sag during writes to EEROM. Most EEROM has a 'high voltage generator' to provide the programming voltage and this briefly draws a high current. If you are using lithium thionyl chloride primary batteries there is a short but severe voltage drop usually attributed to 'passivation effects' as your device wakes up and draws current. That voltage sag will scramble RAM and make it look like data was not preserved during sleep. A big tantalum capacitor across the battery helps but beware the leakage current will shorten the battery lifetime. Careful PCB layout with fat power and ground tracks also helps.

    There are many varieties of lithium batteries. All have high internal energy but some are designed for very low drain such as memory protection and others are better at supplying spike currents. Read the Tadiran and Eagle Picher data sheets for details.


    Saving data in RAM and only writing the ten minute result will save you power if not codespace.

    Can you please explain what is going on here...
    'Word names aliased to Bytes using EXT
    ASM
    W0 = _B0 + 0
    W1 = _B0 + 2
    W2 = _B0 + 4
    ENDASM
    W0 VAR WORD EXT
    W1 VAR WORD EXT
    W2 VAR Word EXT

    I have not seen that construct before.

    Cheers
    BrianT

  4. #4
    Join Date
    Nov 2006
    Posts
    70


    Did you find this post helpful? Yes | No

    Default Good advice

    Thanks for the tips guys.

    Brian, I did some testing a long time ago and got the impression that the PIC10 did not retain RAM in deep sleep (WDT disabled etc). The drain from the EEPROM was a concern, but the system appears to be able to withstand it. I can do multiple reads and writes without going into sleep mode. So, I don't think voltage is a problem, but I think I will go back and do some basic testing again to get to the bottom of the RAM issue. As you say, if I can retain RAM data then I can eliminate a lot of code. Good guessing about those batteries.

    The Word variables are aliased using the EXT command. Read through these threads:
    Bits, Bytes Words and Arrays
    The EXT (external) modifier.

  5. #5
    Join Date
    Nov 2006
    Posts
    70


    Did you find this post helpful? Yes | No

    Default Acknowledge polling

    tenaja,

    I looked into acknowledge polling. I get the concept, but it seems way more expensive than a pause. You gotta have a loop with a shiftin or I2Cwrite command right? Is there a cheap way to do it? Am I missing something?

  6. #6
    Join Date
    Nov 2005
    Location
    Bombay, India
    Posts
    947


    Did you find this post helpful? Yes | No

    Default

    I am sure you will save a lot of room by doing it in ASM.

Members who have read this thread : 1

You do not have permission to view the list of names.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts