Emulate 28X1 external counter on other chips

steliosm

Senior Member
Hello all.

I'm using a 28X1 PicAxe to count the pulses from a small energy meter. I have been using the external counter functionality of the chip, so it counts the pulses in the background while I'm able to talk to the PicAxe through a serial connection and get the number of pulses registered.

I would like to replicate the setup using a smaller chip, since most of the 28X1 power is not used, and also save a bit of space on the board. Ideally, I would need to have the smaller chip to register pulses, could be done though interrupts, and respond to serial requests for sending the data out. I would need to have the data available every minute but the clock accuracy of the PicAxe is not very good, that is why I need to probe the PicAxe from my application. Since I would like to avoid serin, I could use a pulse to trigger an interrupt to make the chip serout the data. So, I know have to have a way to separate interrupt triggers from the pulse reader and from my application.

Anyone has an idea on how I could do that? The pulse rate it's less than 200Hz.
 

hippy

Technical Support
Staff member
It could be a case of expending far more effort than is worthwhile when there's already something which can do the job with a little extra cost. If it's a one-off project I'd say it probably wasn't worth doing than as an academic exercise. If it's a larger commercial product then there may be an argument for it.

Though other PICAXE don't directly support SETTIMER COUNT, it is possible to configure SFR to do the same on some. Have a look on the forum for Timers and and accurate timing / speed of travel projects.
 

steliosm

Senior Member
It could be a case of expending far more effort than is worthwhile when there's already something which can do the job with a little extra cost. If it's a one-off project I'd say it probably wasn't worth doing than as an academic exercise. If it's a larger commercial product then there may be an argument for it.

Though other PICAXE don't directly support SETTIMER COUNT, it is possible to configure SFR to do the same on some. Have a look on the forum for Timers and and accurate timing / speed of travel projects.
I could have used a nice little 1-wire counter chip, but this chip is now discontinued. It's not a matter of cost, but the 28X1 seems like an overkill for this kind of job.

I'll have a go on SFR and timers on the forum.
 

hippy

Technical Support
Staff member
You sometimes have to put that 'overkill for the job' to one side. Most processors aren't used to their full potential, desktop or microcontroller. It's hard to quantify that 'waste' just as it is to quantify how much waste is generated in avoiding that waste.
 

steliosm

Senior Member
Think of it as future expandibility.
There is no need for future expansion, I just need to make it work 'like' the DS2423 chip.

I'm sure there are a lot of projects that are already using this chip and are facing the problem of finding a suitable replacement.
 

BeanieBots

Moderator
I have to agree with Hippy.
Once you have picked a smaller PICAXE, added one or more extra chips, re-designed your code, what have you actually saved?

It will take longer to develop.
More prone to errors.
Probably use more board space.
Probabaly cost more.
Take longer to make.
Take longer to document.

and probabaly a few extras that I've missed.
 

inglewoodpete

Senior Member
How about the 28x1 SMD? It's physically smaller, which is about all you'll gain by downsizing from the DIP 28x1 to something else, as you are proposing.
 

steliosm

Senior Member
How about the 28x1 SMD? It's physically smaller, which is about all you'll gain by downsizing from the DIP 28x1 to something else, as you are proposing.
It's very small for me to solder. I'm actually avoiding any SMD ICs.
I might get lucky playing around with SFR trying to activate the Timer (the 16 bit one) in external counter mode.
 

hippy

Technical Support
Staff member
Have a look at this thread, particularly code posted for Post #60 -

http://www.picaxeforum.co.uk/showthread.php?t=16527

That controls SFR to use timer 1 as a background counter. You'll have to look through the PICmicro and PICAXE datasheets and may have to experiment to see which have the timer 1 input on usable pins and locate where the SFR are and some SFR bits also change between PICmicro.

A forum search on "T1CON" and other related SFR names should bring up more examples.

If 28X1 is overkill, then which PICAXE are acceptable ? It would be worth posting your existing code so we can see what it does, get a feel for its size, as it would be wasted effort to work out how to do it for a particular PICAXE only to find it had gone the other way and wasn't up to the task.
 

steliosm

Senior Member
20X2 would be also be an acceptable option, but the external counter mode in not supported on this chip. Ideally I would like to work with the 08m chip, but the 16bit counter works on a serial pin for programming the picaxe.

There is no code at the moment to do this exact thing. I have a code from a 28X1 based energy meter, reading pulses and updating a simpleLan module's registers. I will use this code as a start.

Thanks for the pointers though.
 

hippy

Technical Support
Staff member
Ideally I would like to work with the 08m chip, but the 16bit counter works on a serial pin for programming the picaxe.
This where you have to dig through the PICmicro datasheets to determine if enabling the timer or clock oscillator / input buffer overrides the Serial In and keeps Serial In as the firmware sees it at a low level so it doesn't keep entering download mode. Ultimately trying it is the only true test.

The Timer 1 LP oscillator does work this way on the 08M which is how one can connect a 32kHz watch crystal direct to it and use that but I haven't looked at whether it could also connect to an external logic signal ( I would expect so ).

You then have to take into account what other consequences doing that has, for example on the 08M, enabling the Timer 1 LP oscillator also uses leg 3, Output Pin 4, so that ceases to be available for use.

I know watch crystals can be used directly attached to a number of PICAXE but don't off-hand recall all which support that and haven't checked for some of the later chips. I do know the 08M works.

http://www.picaxeforum.co.uk/showthread.php?t=13983
http://www.picaxeforum.co.uk/showthread.php?t=7142
 
Last edited:

hippy

Technical Support
Staff member
Rough and ready. Download, leave cable connected, connect a "count" button between Leg 2 ( Serial In ) and +V, connect a "report" button between leg 4 and +V with pull-down 10K to 0V.

When you press the "report" button it will show how many "count" button pushes there have been.

The invoice is in the post :)

#Picaxe 08M
#Terminal 4800

Symbol TMR1L = $0E
Symbol TMR1H = $0F
Symbol T1CON = $10

Poke T1CON,%00001111

Do
If pin3 = 1 Then
Peek TMR1L, b0
Peek TMR1H, b1
SerTxd( #w0, " ")
End If
Loop

Do not connect anything to leg 3, pin 4
 
Last edited:

steliosm

Senior Member
Great, thanks for the code Hippy!

I'm still at work, so I haven't had a change to give it a go. About the SerialIn pin, I understand that it should stay 'low' so the program can run but I can't figure out what I should be looking for at the datasheet concerning Timer1 and the 'GP5/TICKI/OSC1/CLKIN' status. Any tips/pointers on this one?
 

hippy

Technical Support
Staff member
In the 12F683 (08M) datasheet which I have, section 6.0, "Timer 1 with Gate Control".

The convenient magic is in 6.1, "TRISIO<5:4> bits are set when the Timer1 oscillator is enabled. GP5 and GP4 bits read as &#8216;0&#8217; and TRISIO5 and TRISIO4 bits read as &#8216;1&#8217;".

We can enable the oscillator but drive its input from a logic line ( or button to +V ). All that's needed is a POKE to the T1CON SFR to enable the Timer 1 oscillator and set the signal routing etc as shown in the Timer 1 block diagram. Register Bit Descriptions will provide additional explanations and clarifications on how to set the bits and in which SFR's.

There are also notes to watch out for which may vary between devices. For the 08M, 6.2.2, "In Counter mode, a falling edge must be registered by the counter prior to the first incrementing rising edge". If it's a positive pulse being counted then perhaps invert it externally so it's a negative pulse; the rising edge (inverted) will satisfy the note and the falling edge will increment the counter. Or just ignore it, accept the loss of one count when it first starts.

As an aside, that Gate Control ( on leg 3, pin 4 ) could make the 08M very useful for all those speed / pulse-timing measurements that keep cropping up.

A more useful and robust counter example for the 08M attached, using button as described early.
 

Attachments

steliosm

Senior Member
OK, I had this note in 6.6 section in the datasheet. Maybe the datasheet it's too old.

So, if I get this right, the TRISIO5 is set to input and it's set low by pulling it low with a resistor to 0v. Each pulse will set the pin high, wouldn't that suppose to trigger the software download procedure? I noticed that it doesn't and that I'm able to download new firmware after hard resetting the Picaxe.
 

steliosm

Senior Member
I have been experimenting with this concept for a few days now. I used Hippy's code as a base and I expanded on it a bit. I would like to post the source code here, to get some feedback and then make a thread at the finished projects for a 'DS2423 simulator' project.

The modified code counts the pulses and also checks the overflow interrupt flag. Pin1 is used as an interrupt triggering pin and pin2 as a serout pin for the data. Bot pins are connected to the USB-2-ttl cable. Data coming from the PC on pin1 will trigger the interrupt and PicAxe will send the values out.

Code:
'
' Picaxe 08m Pulse Counter v 0.1
' Simulate part of the operations done by DS2423 counter IC 
' by Stelios
' Based on work done by Hippy
'

' Define the symbols
Symbol TMR1L = $0E
Symbol TMR1H = $0F
Symbol T1CON = $10
Symbol IntFlag = $0C
Symbol MULT = b4
Symbol OverFlow = b0

' Initialize the values
' Make initial count equal 1 
' We are skipping the first pulse count so we need to add one
Poke TMR1L, $1
Poke TMR1H, $0

' Set the multiplier value to be 0
let MULT = 0

' Enable Timer1 as counter
Poke T1CON, %00001111

' Set the interrupt on pin1 to trigger when it's low
setint %00000000, %00000010

main:
   ' Check the Overflow flag
   peek IntFlag, OverFlow
   ' Check if we had an overflow
   if bit0 = 1 then
     ' Increase MULT value
     MULT = MULT +1
     ' Clear the overflow flag
     Poke IntFlag, %00000000
   end if
   ' Do nothing loop 
   pause 10000
   goto main

interrupt:
   ' Get the timer 1 values
   Peek TMR1L, b2
   Peek TMR1H, b3

   ' Push out the data
   Serout 2, t2400, (#MULT, ":", #w1, CR, LF)
   ' Re-Set the interrupt
   setint %00000000, %00000010
   return

A haven't set the picaxe to store the values to the EEPROM, since I believe it will destroy the EEPROM eventually. Since the Picaxe is not doing anything most of the times it could possible be battery backed up. If you only need the number of pulses between a certain period, then I guess you don't need the battery at all.

Comments are welcomed!
 

hippy

Technical Support
Staff member
A few points -

Adding 1 for the 'missed first pulse' is technically invalid as you may not have had the first pulse at that time. Best way is to invert the pulse so it never misses any as described earlier.

You're not checking for count changing when reading the two counter bytes. If count is 1:255 (511), you read the 255, a pulse occurs, it goes to 2:0 (512), you read the most significant, then report 2:255 (767) which is massively out, and the next reading is 2:1 (513) which appears to have gone backwards. You'll get the same problem if you read MSB first; 1:255 (511), then 1:0 (256), then 2:1 (513).

This is probably considerably worse when there's an overflow which should increase the most significant word of the 32-bit count value but doesn't.

Clearing the timer interrupt with "POKE <adr>, %00000000" is a bad idea. You should read the register and then clear only that interrupt bit and write all other bits back as they were.

I personally wouldn't use interrupts at all, just poll in places where you know the data returned will be valid. I'd also not use the interrupt flag but handle that by checking when the current reading is less than the last. Keep the latest 32-bit reading in memory and report that back.
 

hippy

Technical Support
Staff member
Untested ...

Code:
#Picaxe 08M
#Terminal 9600

Symbol TMR1L         = $0E
Symbol TMR1H         = $0F
Symbol T1CON         = $10

Symbol this.lsw      = w0 ' b1:b0
Symbol this.lsw.lsb  = b0
Symbol this.lsw.msb  = b1

Symbol this.msw      = w1 ' b3:b2

Symbol last.lsw      = w2 ' b5:b4

Symbol check.lsw.msb = b6

SetFreq M8

Poke T1CON,%00001111

Poke TMR1H, 0 : Poke TMR1L, 0

Do
  Gosub CountPulses
  If pin3 = 1 Then
    SerTxd( #this.msw, ":", #this.lsw, CR, LF )
    Do 
      Gosub CountPulses
    Loop Until pin3 = 0
  End If
Loop

CountPulses:
  Do
    Peek TMR1H, this.lsw.msb
    Peek TMR1L, this.lsw.lsb
    Peek TMR1H, check.lsw.msb 
  Loop Until this.lsw.msb = check.lsw.msb
  If this.lsw < last.lsw Then
    this.msw = this.msw + 1
    last.lsw = this.lsw
  End If
  Return
 

steliosm

Senior Member
Hello Hippy and sorry for my late response.

A few points -

Adding 1 for the 'missed first pulse' is technically invalid as you may not have had the first pulse at that time. Best way is to invert the pulse so it never misses any as described earlier.
Yes, you are right about that, I will have a a look for the inverted pulses and see how it goes.

You're not checking for count changing when reading the two counter bytes. If count is 1:255 (511), you read the 255, a pulse occurs, it goes to 2:0 (512), you read the most significant, then report 2:255 (767) which is massively out, and the next reading is 2:1 (513) which appears to have gone backwards. You'll get the same problem if you read MSB first; 1:255 (511), then 1:0 (256), then 2:1 (513).

This is probably considerably worse when there's an overflow which should increase the most significant word of the 32-bit count value but doesn't.
I can't figure this out. What I do is count the 2 bytes for the pulses an have a small integer to count the times the T0mer has overflowed. I call the second counter a multiplier. Every time the overflow flag it set I just increment the multiplier, so when I get 1:1 as an output I know that I had an overflow and one pulse counted. So, the total pulses are Multiplier*65535 + Pulses = 65535+1 = 65536.

Clearing the timer interrupt with "POKE <adr>, %00000000" is a bad idea. You should read the register and then clear only that interrupt bit and write all other bits back as they were.
Yes, you are right about that. I'll just pull the value from the register to a byte variable and switch the bit before Poking back.
 

hippy

Technical Support
Staff member
The issue with getting the internal count is what happens if a pulse occurs and the counter increments between reading the internal LSB and the MSB. It may seem unlikely this will happen but Sod's Law says it will.

Code:
Pulse   MSB:LSB                 b1:b0   Reading
  |       0:255
  |       0:255  Read LSB to b0  -:255
  |       0:255
  |       0:255  Read MSB to b1  0:255  255
  |
  |       0:255
  |       0:255  Read LSB to b0  -:255
  |       0:255
 ###      1:000
  |       1:000  Read MSB to b1  1:255  511 <--- Error
  |
  |       1:000
  |       1:000  Read LSB to b0  -:000
  |       1:000
  |       1:000  Read MSB to b1  1:000  256
A similar thing can happen with your 'multiplier' ( more correctly, the most significant word ).

If a pulse increments the counter from 255:255 to 0:0 you should count this in your 'multiplier', so you should go from 0:255:255 to 1:0:0, but if the counter rolls over, an interrupt occurs to send a reading before the 'multiplier' is incremented you'll send 0:0:0.

Similarly with poking the overflow bits. If you Peek the byte, clear the bit, and Poke it back, if the Firmware has changed some other bit between your Peek and Poke you will overwrite that. That's not as likely to happen but it's a possibility so best to design code such that it's not even a possibility.
 
Last edited:

steliosm

Senior Member
Yes, I see what you mean Hippy and you are right.
I need to have a good check routine either on the Picaxe or the script running on the PC to check the values.
The subroutine on your previous post seems to be able to to that. I'll put that on the program and let it run for a few days.
 
Top