multiple PWM capture

Discussion specific to the ZX-1281 and ZX-1280 microcontrollers as well as the ZX-1281 and ZX-1280 Dev Boards.
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

sturgessb wrote:When its waiting for the idle state and to reach desired logic, does it only halt the task its in, or the entire mcu?
PulseIn() effectively halts everything while it is running. Interrupts are disabled and no task switching occurs. Note, however, that the RTC is updated for missed ticks after the pulse is received but other interrupt driven functions are dead in the water (e.g. serial I/O).

PulseIn() is completely implemented in software - that's why interrupts must be disabled. InputCapture(), on the other hand, is implemented in hardware and can read the widths of one or more pulses without shutting down everything else.
- Don Kinzer
sturgessb
Posts: 287
Joined: 25 April 2008, 6:34 AM
Location: Norwich, UK

Post by sturgessb »

Thanks for the help guys, got it working nicely with external interrupts on the zx128ne.

Is it possible to have an ISR driven by a PinChange Interrupt, if i wanted to put this code onto the 644 rather than the 128?

The docs show PCINT0 - 3. Does this equate to individual pins or Ports?

how are these enabled for ISR use? on the 128 I do this...

Code: Select all

Register.EICRA = Bx0101_0101 
	Register.EICRB = Bx0101_0101
	Register.EIMSK = Bx0000_1111     'enable INT0,1,2,3
what would be the equivilent for the 644 using PCINT0 - 3

Also, on the 644 and 328, are any of the interrupts needed for I2C?
Last edited by sturgessb on 05 January 2009, 14:39 PM, edited 1 time in total.
mikep
Posts: 796
Joined: 24 September 2005, 15:54 PM

Post by mikep »

sturgessb wrote:Is it possible to have an ISR driven by a PinChange Interrupt, if i wanted to put this code onto the 644 rather than the 128?

The docs show PCINT0 , 1 , 2, 3. Does this equate to individual pins or Ports or pins?
Good news on getting it working. Each pin change interrupt relates to a whole port. You turn on the interrupt for specific I/O pins and then inside the ISR you will need to determine which pin caused the pin change interrupt. The 644p datasheet is your friend here. The relevant registers are:
PCICR - Pin Change Interrupt Control Register
PCMSKx – Pin Change Mask Register x (where x is 0, 1, 2, or 3

The ISR needs to examine the state of the pins (Register.Pinx) to determine what changed. XOR can be your friend here if you save the previous state.
Mike Perks
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

As Mike pointed out, the pin change interrupts are sensitive to any change, either the leading or the trailing edge of the pulse. The external interrupt can be programmed to operate the same way but it seemed simpler to configure it first for a rising edge and then to reconfigure it for a falling edge, etc.

If you have all four PWM inputs on the same port, you'll only need one ISR but you'll need code to figure out which pin or pins changed as Mike indicated. Alternately, you could choose to put each PWM input on a different port. The would increase the amount of setup work required and would require four separate ISRs but it would obviate the need to try to determine which pin changed. The latter strategy would not work on a ZX-328n because it only supports three ports: B, C and D.
strugessb wrote:Also, on the 644 and 328, are any of the interrupts needed for I2C?
Interrupts are not used to implement I2C master mode but an interrupt is required to implement I2C slave mode.

One further note: you should do some research to determine the waveform generated for the four PWM channels by the controller. Some web pages that I've looked at show a waveform where the trailing edge of the channel 1 pulse is coincident with the leading edge of the channel 2 pulse and so on down the line. If this is indeed the case (or if the leading edge of one channel follows very closely the trailing edge of the preceding channel) you'll need to code the ISR carefully to allow for that timing.
- Don Kinzer
sturgessb
Posts: 287
Joined: 25 April 2008, 6:34 AM
Location: Norwich, UK

Post by sturgessb »

Thanks Mike

So...

Code: Select all

	Register.SREG = Bx1000_0000
	Register.PCICR = Bx0000_0001
	Register.PCMSK0 = Bx0000_0001
Would enable which pin on the zx-24? pin 12?

Code: Select all

ISR PCINT0()
	tempint = tempint + 1
END ISR
doesnt seem to work, am i missing something?
spamiam
Posts: 739
Joined: 13 November 2005, 6:39 AM

Post by spamiam »

dkinzer wrote:Some web pages that I've looked at show a waveform where the trailing edge of the channel 1 pulse is coincident with the leading edge of the channel 2 pulse and so on down the line.
This round-robin method of doing the PWM should be relatively easy to handle. If the PC interrupt is set up to trigger on both edges, then you have to do the XOR of the port with the last port state, then go sequentially through each of the "true" bits. If the state change on a particular pin was a rising edge, then grab the timer reading and save it.

If the edge was a falling edge, then grab the timer reading and subtract it from the saved value. Then store that resulting value somewhere for future processing. Probably a flag would need to be set as well.

One question would be about when to reset the timer to zero. It would be nice to be able to reset the timer rather than let it wrap around as it overflows. However it might take too much effort (and another timer?) to do.

This still does not answer the question of how accurate (how often the same measurement results in the same answer) and how precise (how different measured variables need to be to get the reading of the two to be different) this is going to be.

An interrupt that takes a long time to process will reduce the overall precision. An interrupt that takes a variable amount of time to process will reduce accuracy. Other interrupts occuring at the sime time will also reduce accuracy.

The only way to find out how it will actually work is to try it and see. I think you are well along the process to being able to try it out!

Oh, to answer the question of whether I2C requires interrupts. The answer is YES. The hardware I2C functions do use interrupts. If you do your own software I2C then you will not need interrupts. If you were concerned about the latency in servicing a Pin Change interrupt, then it is probably better to use the hardware I2C rather than use a new task for the software I2C. The added overhead to OS to serivce the extra task is likely to be worse than the I2C interrupt.

-Tony
sturgessb
Posts: 287
Joined: 25 April 2008, 6:34 AM
Location: Norwich, UK

Post by sturgessb »

spamiam, I have tried it, it works well, accuracy and resolution is more than enough, with a 16bit timer anyway.

Just cant get it working on PinChange Interrupts, can't get the ISR to fire.
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

sturgessb wrote:Just cant get it working on PinChange Interrupts, can't get the ISR to fire.
Which pins are you using? Can you show the code that you're trying.
- Don Kinzer
sturgessb
Posts: 287
Joined: 25 April 2008, 6:34 AM
Location: Norwich, UK

Post by sturgessb »

I have a pulse line going into pin 12. on the zx-24.


code is.....

Code: Select all

Public tempint as INTEGER

Sub Main()

Register.SREG = Bx1000_0000
Register.PCICR = Bx0000_0001
Register.PCMSK0 = Bx0000_0001

If Semaphore(Register.Timer1Busy) Then
	Register.TCCR1A = 0
	Register.TCCR1B = &H02
	Register.TCCR1C = 0
End If

End Sub

ISR PCINT0()
  tempint = tempint + 1
END ISR
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

sturgessb wrote:

Code: Select all

	Register.SREG = Bx1000_0000
	Register.PCICR = Bx0000_0001
	Register.PCMSK0 = Bx0000_0001
Would enable which pin on the zx-24? pin 12?
PCINT0 corresponds to PortA (PCINT1->PortB, etc.) so the code above would enable a pin change interrupt on pin 20 of a 24-pin ZX. If you want to use pin 12 (PortC) then you need to use PCINT2.

Generally speaking, you shouldn't manipulate Register.SREG directly as you've shown. The global interrupt flag is enabled by default. If you should need to turn it off and on (which, for this purpose, you don't), use DisableInt()/EnableInt().
- Don Kinzer
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

sturgessb wrote:I have a pulse line going into pin 12. on the zx-24.
You need to use PCINT2:

Code: Select all

Public tempint as INTEGER

Sub Main()
  If Semaphore(Register.Timer1Busy) Then
    Register.TCCR1A = 0
    Register.TCCR1B = &H02
    Register.TCCR1C = 0
  End If
  Register.PCIFR = &Hff
  Register.PCMSK0 = Bx0000_0001
  Register.PCICR = Bx0000_0100  ' PCINT2, PortC
End Sub

ISR PCINT2()
  tempint = tempint + 1
END ISR
Last edited by dkinzer on 05 January 2009, 15:51 PM, edited 1 time in total.
- Don Kinzer
sturgessb
Posts: 287
Joined: 25 April 2008, 6:34 AM
Location: Norwich, UK

Post by sturgessb »

ah yes, thanks. I was incorrectly assuming the PC numbers on the schematic referred to the PCINT numbers.

now onto the port state comparison... Im so out of my depth here!
Last edited by sturgessb on 05 January 2009, 15:57 PM, edited 1 time in total.
sturgessb
Posts: 287
Joined: 25 April 2008, 6:34 AM
Location: Norwich, UK

Post by sturgessb »

hmmm for some reason thats not working. When i used my orignal Port A code and changed to pin 20, it worked. But switched to exactly your code with Port C and PCINT2 /pin 12 and nothing. Weird.

I could just use port a but was hoping to keep that free for adc use. (Fixed)
Last edited by sturgessb on 05 January 2009, 16:07 PM, edited 3 times in total.
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

sturgessb wrote:Im so out of my depth here!
Otherwise known as an extraordinary opportunity to learn.
- Don Kinzer
sturgessb
Posts: 287
Joined: 25 April 2008, 6:34 AM
Location: Norwich, UK

Post by sturgessb »

ah figured it, needed to be Register.PCMSK2
Post Reply