Strange interrupt behaviour?

hey!

sorry for spamming the forum with another interrupt issue, but i started over with some very basic experiments on the interruptfunctions.

so here is what i found out...

void test()
{
  // do nothing
}

void setup()
{
  Serial.begin(9600);
  attachInterrupt(0, test, CHANGE);
  cli();
//sei();
}

void loop()
{
  Serial.println(millis());
  delay(100);
}

millis() don't seem to work whenever i disable the interrupts with cli(). i only receive '0' in the serial output... using delays also doesn't work - the program stucks. if i enable interrupts again by using the sei() command everything works fine... why?

this behaviour seems to be my main problem when i try to interface the ps/2 touchpad, because i want the pad to be read after an interrupt occurs at the clock-line (clock falling, means that the pad is ready to send data), but then i need to disable the interrupt, because i want to receive data (which means, that the clock is going low-high-low-hing.... all the time). for timing the protocol i also have to use delayMicroseconds...

anybody out there, who knows how to fix it or how to work arround?

thanks in advance for every thought on that, hans

The values returned by millis() are incremented by an interrupt, so if you disable interrupts, they stop incrementing. delay() also depends on these values so it doesn't with interrupts disabled. delayMicroseconds() on the other hand, doesn't depend on interrupts.

What you can do, though, is only disable your interrupt handler, not all interrupts. Just call detachInterrupt(0) instead of cli().

yeah! i tried it again, replacing everything with attachInterrupt and detachInterrupt - it works the same way now - interrupts take place, but ONLY if i add pinMode(CLOCKLINE, INPUT) to the main-loop. (the data i receive is weird again...)

maybe there is the problem: the ps/2 example from the playground switches between INPUT and OUTPUT all the time, so that one only need 1 pin for the clock- and 1 pin for the dataline.

may it be possible that this causes the interrupts not to work properly?

It's certainly possible that the external interrupts (i.e. the ones used by attachInterrupt) don't fire unless the pin is set as an input. Is it possible to set the pin back to an input when you're expecting to receive data from it (and thus trigger an interrupt)?

it is possible - but: how fast is switching pins from input to output and vice versa? i think the weird values i reveive are a result of timingproblems…

It's possible. You might try using DDRx and PORTx and PINx instead. I think you can find some information if you try search Google for Arduino and those terms.

yes. i read something about it in the (great) bitshifting-tutorial in the playground. so this way is faster then pinMode()? thats cool - because then there might be a chance... :)

it is working now. thank you mellis! wooohooo! 8-)

i think driving the ports directly through their register saved the cycles that made the touchpad skip out of clock, causing the weird values...

both pads together are also working but not that fine. i'm thinking about doing the bitshifting locally on my computer, not at the arduino directly as i do by now.

can this sanction save a comperatively amout of cycles so that reading the pads gets more reliable?

Dunno. Bit-shifting should be relatively fast compared to serial communication. You should definitely try increasing the baud rate you're using to communicate with the computer.

only a few shitty values left :slight_smile:

the key to success was not to trigger interrupt on high2low-transition (as mentioned in their applicationguide!),
but on low-state. additionally, after receiving the interrupt i put the clockline low, to hold back the incoming data.
then, immediatly befor reading the data, i released the clockline by setting it as input.

now i’m trying to speed things up by cleaning up the serial communication. here’s what i need so send:

  • 4 Integers, 0-2000
  • 10 Booleans, 0/1
    i think the easiest way to do it is to send the four integers and then put the 10Boolean in 2 bytes.
    for that i need some help with bitshifting, because i dont know a slick way to insert all the 10 bools into the
    bytes.

i would do it like this (for the first byte).

for(i=0; i<5; i++){
  if(myboolean[i])
    mybyte1 |= (1<<i);
  else
    mybyte1 &= ~(1<<i);
}

but it think there is a way to store all the bools at once…

thanks in advance,
hans

damn ... too easy:

byte mybyte;
mybyte = (bool1 * 128) + (bool2 * 64) + (bool3 * 32) + (bool4 * 16) + (bool5 * 8) + (bool6 * 4) + (bool7 * 2) + (bool8 * 1);

... there you are - stored 8 bools in only one byte :)