'Count' and 'Servopos@ commands on OM2

Hi,
Can I use 'count' and 'Servopos' commands (on separate pins i.e count on C.1 and Servopos on C.2) in the same programme?
The syntax checker seems happy with it but, will it work in practice? :rolleyes:
Thanks?
 

AllyCat

Senior Member
Hi,

Yes, if you link the two pins together, then I'm fairly sure it will work fine. But remember that COUNT is a "blocking" command so the Program can't do anything else (i.e. probably not Interrupts) whilst it is executing.

A more interesting question is if it's possible to use PWMOUT and COUNT, or an Interrupt, on the same pin. In principle that's not possible because PICaxe Basic needs to set each pin as either an Output or an Input. But I believe it has been reported that it is (sometimes) possible (due to the nature of the Base PIC chip Hardware), which might be quite useful, for example to set up a "Timer" Interrupt on an M2.

Cheers, Alan.
 

bpowell

Senior Member
I don't see why you couldn't use COUNT on C.1 and Servopos on C.2 ... as Allycat pointed out, COUNT is a blocking command, but I'd assume once you've sent a Servopos command, you're really just establishing a PWM on that pin, so it should go happily along regardless of a blocking command, but, only one way to find out!

I've not heard of a PIN that can be an input and an output at the same time ... Allycat, do you have some examples of that?
 

AllyCat

Senior Member
Hi,

Thinking more about this: Certainly you can use both commands in the same program, but if the question is really: "Will a program using COUNT and SERVO..... commands always work perfectly?", then the short answer is probably NO. The Servo Output Pulse (and hence the servo position) may "Jitter" whenever the COUNT command is executed.

It's not a direct "Timer Hardware Conflict" because COUNT uses purely a software counter/timing routine, but (I believe) it disables interrupts to avoid missing any Count Pulses. However, the Servo Pulse(s) are generated by internal interrupts (with a 20 ms cycle from Timer 1), so the spacing between servo pulses might be extended, or more seriously a Servo pulse itself may be extended whilst the COUNT executes. The alternative would cause the COUNT value to have potential errors (omissions) whenever a Servo pulse is being generated.

One solution is to use a PWM output to drive the Servo, but there are fewer PWM Output-capable pins than Servo Output pins. Also, the nominal 20ms cycle time must be shortened, even with the default 4MHz clock frequency, and the pulse-width resolution cannot be as high as the normal Servo pulses (16us v 10 us).

Generally the "best" solution is to NOT use the COUNT instruction, but the altenative depends very much on the nature of the pulses that you want to count, particularly their repetition frequency. For lower frequencies an Interrupt-counting routine might be best. For higher, constant frequencies, usually a PULSIN (or several) is the best solution, which possibly could be sychronised to avoid any "collisions" with the Servo pulse(s).
---------
OT :
There are several ways that a pin can be used as both input and output "at the same time". For example an internal WeaK Pullup Resistor can be activated/disabled on a defined Input pin, and there are various ways that pins can be used in a "Wired Or" mode: For example the READTEMP command (for an DS18B20 sensor) or the I2C Bus uses pins in a combined "I/O" mode.

But for a pin to facilitate an internal connection (e.g. to implement a PWM-timer interrupt on a single pin), the pin can remain as an Output. The "Base PIC" hardware can read back the digital level on an Output pin, and even the PICaxe can do this via the OUTPINS variable. The problem is that, to be "helpful" to the Programmer, the PICaxe interpreter automatically switches the Data Direction registers (DIRs) when certain commands are executed; for example HIGH , LOW , etc. set the nominated pin as an Output and IF pinC.x = 1 THEN .... , etc. sets the named pin as an Input (if it isn't already). So the question is whether (for example) the SETINT command forces its relevant pins to being Inputs (unlikely) and whether the "Interrupt" signals are derived from the (inactive) input buffer or from the true (output) pin level (Outpins), or from somewhere else.

Further discussion is likely to involve PEEKSFR and POKESFR commands, and the Microchip Base PICaxe Data Sheet, etc. which is probably rather deep for this thread at the moment, so I'll close here for now.

Cheers, Alan.
 

bpowell

Senior Member
There are several ways that a pin can be used as both input and output "at the same time". For example an internal WeaK Pullup Resistor can be activated/disabled on a defined Input pin, and there are various ways that pins can be used in a "Wired Or" mode: For example the READTEMP command (for an DS18B20 sensor) or the I2C Bus uses pins in a combined "I/O" mode.
The READTEMP command and I2C both flip the pin from output to input and back ... so it's not "At the same time"

I'll give ya the weak pull-up trick ... that puts a high-signal on an input pin ... but that's a limited use-case for sure .... how do you drive that same pin low? The best you can do is kill the pull-up and let it float.

As to the rest of the topic ... if ServoPOS and COUNT are both using software vs. CIP ... then yeah, they likely will not work as expected if used in the same program.
 

AllyCat

Senior Member
Hi,
The READTEMP command and I2C both flip the pin from output to input and back ... so it's not "At the same time"
IMHO, the "wired OR" use of a pin, e.g. as used by READTEMP, the I2C Bus and particularly as an Interrupt Request line is a genuine, instantaneous bidirectional use of a pin. At any instant, both the PIC(axe) and the External Circuit can Read the pin status and either could request control of a/the Bus (unless it has already been claimed). The common "Open Collector/Drain" configuration with a pullup resistor, actually uses Negative Logic, i.e. the OR pin is Idle High and Active Low (often named as /INT, etc.).

Then, some Protocol may be required, for example to identify which of multiple Interrupt sources or DS18B20 sensors is to be interrogated. The READTEMP command doesn't actually support multiple sensors on a single pin, but a PICaxe can read them via its OWIN and OWOUT commands (X2s only).

I'll give ya the weak pull-up trick ... that puts a high-signal on an input pin ... but that's a limited use-case for sure .... how do you drive that same pin low? The best you can do is kill the pull-up and let it float.
The base of a bipolar transistor can be connected directly to an "Input Only" pin and activated by enabling/disabling the relevant Weak Pullup resistor. Or for CMOS devices an external "even weaker PullDown" resistor (say 100k+) can be used, which is literally all that is required for example to control the Chip Enable or similar of another logic device or sensor, etc., from an Input Only pin (of which the 08M2 effectively has 2 of its 6 signal pins).

If you're Bit Banging a Wired-Or protocol on a bidirectional pin, you can just switch between LOW and INPUT <pin> (i.e. Tri-State) commands, but it's also possible to write one or more bits directly to the appropriate register/variable, i.e. pinsC or dirsC (Data Direction), etc., for example pinsC = outpinsC xor 4 should toggle pin C.2 .
------------

The OP didn't indicate the purpose of his COUNT command, but it might be possible to reliably use it to measure a High Frequency, or the inverse PULSIN command (to measure the period of a lower, constant frequency) without any interference with the Servo command: A single servo pulse has a maximum duration of around 2.5ms, with a gap of 17.5ms to the next, so there is a "Window" of at least 15 ms where a COUNT or PULSIN could be executed. That may be sufficient to read a full byte value, and if necessary SERVOPOS can be used with a SETFREQ M16.

The are various ways that the Program code could be synchronised between the servo pulses, but as mentioned above, attempting to read the Servo Pulse from the pin itself could be problematic. Normally, I would write the program around a PEEKSFR Timer1, ... (SFR Addresses $17 : $16) which triggers the Servo Pulses whilst counting up from 45536 to 65535 (i.e. for 20 ms). But Timer 1 is also the first prescaler (divider) for the "time" Variable, so for a modest throughput of COUNT or PULSIN you could try (untested):
Code:
do
   lasttime = time
   do : loop until time <> lasttime     ; Wait for time to increment
   pause 200                            ; Wait around 2 ms, depending on maximum width of Servo Pulse(s), etc.
   count C.1,10,value                   ; Count for 10ms
   sertxd(cr,lf,#value)
; etc.
loop
Cheers, Alan.
 
Last edited:
Top