ATtiny85: Pin Change Interrupt fails to trigger

Go To Last Post
8 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi all,

 

I have a very peculiar problem with my ATtiny85: the pin change interrupt doesn't want to trigger when I try to time the discharge time of a capacitor. The same interrupt triggers just fine if I pull up the pin with a resistor, then touch it with a wire connected to GND. Below the schematic of my setup, the interrupt I try to trigger is on CapPos/PB1. This is for measuring the EC of a liquid - PB1 is set sometimes to output (to charge the capacitor), sometimes to input (to time the discharge of that capacitor via J1 and pin EC/PB4.

 

The discharge time of the capacitor - and the time after which the interrupt is expected - is normally in the tune of 1-1000 microseconds. As the interrupt works with the wire (a change from Vcc to GND on the pin as instantaneous as possible) it gives me the feeling that the change is missed becaues it's too slow/gradual. I do however really rely on this interrupt to get the accuracy in timing that I need, especially on the low end of the time scale.

 

The relevant function & ISR are below the schematic. There's some debug stuff in it: I've tried various ways to detect the interrupt, it's just not triggered, even though I very often have PB1 low after the timeout, even though bool interrupted is false. In the original code it was dischargeCycles that was set to the current value of the timer - as that didn't do anything (the variable remained 0) I changed that to this bool. Both are declared volatile.

 

This function works perfectly fine on an ATmega328 - after amending some of the register names of course - the interrupt triggers here reliably. Same pins, same external components.

 

The relevant function:

/*
   Take a single reading from the EC probe.
*/
void readEC() {
  uint32_t totalCycles = 0;
  uint32_t startTime = 0;
  data[0] = 0;
  data[1] = 0;
  data[2] = 0;
  for (uint8_t i = 0; i < 64; i++) {

    // Stage 1: charge the cap, positive cycle.
    DDRB |= (1 << CAPPOS);                        // CAPPOS output.
    DDRB |= (1 << CAPNEG);                        // CAPNEG output.
    DDRB &= ~(1 << ECPIN);                        // ECPIN input.
    PORTB |= (1 << CAPPOS);                       // CAPPOS HIGH: Charge the cap.
    PORTB &= ~(1 << CAPNEG);                      // CAPNEG LOW.
    PORTB &= ~(1 << ECPIN);                       // ECPIN pull up resistor off.
    TCNT1 = 0;

//    startTime = micros();
//    while (micros() - startTime  < CHARGEDELAY) {};// Wait for cap to charge.
    TCNT0 = 0;
    while (TCNT0 < (CHARGEDELAY >> 3)) {}

    // Stage 2: measure positive discharge cycle by measuring the number of clock cycles it takes
    // for pin CAPPOS to change from HIGH to LOW.
    dischargeCycles = 0;
    TCNT1 = 0;                                    // Reset the timer.
    DDRB &= ~(1 << CAPPOS);                       // CAPPOS input.
    DDRB |= (1 << ECPIN);                         // ECPIN output.
    PORTB &= ~(1 << CAPPOS);                      // CAPPOS pull up resistor off.
    PORTB &= ~(1 << ECPIN);                       // ECPIN LOW.
    PCMSK |= (1 << CAPPOS);                       // Set up the pin change interrupt on CAPPOS.
//    startTime = micros();
    interrupted = false;
    TCNT0 = 0;
//    while (micros() - startTime  < EC_TIMEOUT) {
    while (TCNT0 < (EC_TIMEOUT >> 3)) {
      if (dischargeCycles)
        break;
      if (interrupted)
        break;
    }
    PCMSK &= ~(1 << CAPPOS);                      // Clear the pin change interrupt on CAPPOS.
    if (interrupted) {
      data[0]++;  // Interrupt recorded.
    }
    else {
      data[1]++;  // Interrupt didn't happen - timeout.
      if ((PINB & (1 << CAPPOS)) == 0) {
        data[2]++; // No interrupt recorded but pin is low.
      }
    }

    totalCycles += dischargeCycles;

    // Stage 3: charge the cap, negative cycle.
    DDRB &= ~(1 << ECPIN);                        // ECPIN input
    DDRB |= (1 << CAPPOS);                        // CAPPOS output
    PORTB &= ~(1 << CAPPOS);                      // CAPPOS LOW
    PORTB |= (1 << CAPNEG);                       // CAPNEG HIGH: Charge the cap
    TCNT1 = 0;
//    startTime = micros();
//    while (micros() - startTime  < CHARGEDELAY) {};// Wait for cap to charge.
    TCNT0 = 0;
    while (TCNT0 < (CHARGEDELAY >> 3)) {}

    // Stage 4: discharge the cap, compenstation cycle.
    DDRB &= ~(1 << CAPPOS);                       // CAPPOS input
    DDRB |= (1 << ECPIN);                         // ECPIN output
    PORTB |= (1 << ECPIN);                        // ECPIN HIGH

    // delay based on dischargeCycles
    TCNT1 = 0;
//    startTime = micros();
    TCNT0 = 0;
    if (dischargeCycles) {
//      while (micros() - startTime < (dischargeCycles >> TIMESCALE)) {};
      while (TCNT0 < ((dischargeCycles >> TIMESCALE) >> 3)) {}
    }
    else {
//      while (micros() - startTime  < CHARGEDELAY) {};
      while (TCNT0 < (CHARGEDELAY >> 3)) {}
    }
  }
  // Disconnect EC probe: all pins to INPUT.
  DDRB &= ~(1 << CAPPOS);                         // CAPPOS input
  DDRB &= ~(1 << CAPNEG);                         // CAPNEG input
  DDRB &= ~(1 << ECPIN);                          // ECPIN input
  PORTB &= ~(1 << CAPNEG);                        // CAPNEG pull up resistor off.
  PORTB &= ~(1 << ECPIN);                         // ECPIN pull up resistor off.

  uint16_t averageCycles = (totalCycles >> 6);
  //
  //  // Return the actual dischargeCycles in data[1] and data[2], useful for debugging and used for calibration.
  //  data[0] = 0;
  //  data[1] = (averageCycles >> 8) & 0xFF;
  //  data[2] = (averageCycles >> 0) & 0xFF;
  return;
}

ISR(PCINT0_vect) {
  interrupted = true;
//  dischargeCycles = TCNT1;
//  PCMSK &= ~(1 << CAPPOS);                      // Clear the pin change interrupt on CAPPOS.
}

 

 

 

 

Last Edited: Sat. Sep 30, 2017 - 06:38 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

wvmarle wrote:
The relevant function:

Sorry -- please post a complete test program that demonstrates your symptoms.  Tell what you expect to happen; tell what >>is<< happening.  Tell how you are testing.  Tell toolchain, version, and optimization settings.

 

1)  What are the voltage levels, >>right on the AVR pins<< ?

2)  Show the declaration for "interrupted".  Looking for "volatile"...

3)  Show GIMSK manipulation.

4)  Show where global interrupts are enabled.

 

In short: 

post a complete test program that demonstrates your symptoms.

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Sun. Oct 1, 2017 - 12:22 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

"... the interrupt I try to trigger is on CapPos/PB1 ..." which is PCINT1 but the only ISR shown is for PCINT0
It would help if you show what the values of CAPPOS, ECPIN, etc are., they probably agree with the schematic, but .....

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mikech wrote:
"... the interrupt I try to trigger is on CapPos/PB1 ..." which is PCINT1 but the only ISR shown is for PCINT0 It would help if you show what the values of CAPPOS, ECPIN, etc are., they probably agree with the schematic, but .....

From the ATtiny documentation I learned there is ONE PCINT register and ALL pin change interrupts go to that one and only register (after which it is up to the software to figure out which pin was triggered - and as I set only one PC interrupt that's easy.

 

Anyway, this works. When closing/opening J1 the LED lights up.

 

The code running this:

#include <TinyWireS.h>

#define LED PB3
#define PCPIN PB1

volatile bool interrupt;

// Advance declaration of callback functions.
void wireRequest(void);
void wireReceive(void);

void setup() {
  pinMode(LED, OUTPUT);
  digitalWrite(LED, LOW);

  GIMSK |= (1 << PCIE);                       // Enable pin change interrupts.
  PCMSK |= (1 << PCPIN);                      // Trigger an interrupt on state change of PCPIN.
}
 
void loop() {
  if (interrupt) {
    interrupt = false;
    PCMSK &= ~(1 << PCPIN);                     // Disable pin change interrupt on PCPIN.
    digitalWrite(LED, HIGH);
    delay(500);
    digitalWrite(LED, LOW);
    PCMSK |= (1 << PCPIN);                       // Enable pin change interrupt on PCPIN.
  }
}

ISR(PCINT0_vect) {
  interrupt = true;
}

void wireReceive(uint8_t n) {
  char data[n];
  for (uint8_t i = 0; i < n; i++) {
    if (TinyWireS.available())
      data[i] = TinyWireS.read();
    else
      break;
  }
}

void wireRequest() {
  TinyWireS.write(1);
  TinyWireS.write(2);
  TinyWireS.write(3);
}

The I2C code is included to make sure it doesn't interfere with my interrupt (as it uses interrupts itself).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:

wvmarle wrote:
The relevant function:

Sorry -- please post a complete test program that demonstrates your symptoms.  Tell what you expect to happen; tell what >>is<< happening.  Tell how you are testing.  Tell toolchain, version, and optimization settings.

 

Arduino IDE v1.8.1

Using a Pro Mini clone as programmer.

All default settings.

 

theusch wrote:

1)  What are the voltage levels, >>right on the AVR pins<< ?

Vcc = 5V, GND = 0V. No other power connections.

 

Quote:

2)  Show the declaration for "interrupted".  Looking for "volatile"...

3)  Show GIMSK manipulation.

4)  Show where global interrupts are enabled.

 

Complete code below.

 

/*
   I2C library used:
   https://github.com/nadavmatalon/TinyWireS
*/

#include <TinyWireS.h>

#define CAPPOS PB1                            // digital pin for cap and EC probe
#define CAPNEG PB4                            // digital pin for cap and analog in for NTC probe.
#define ECPIN PB3                             // digital pin for EC probe
#define CHARGEDELAY 40                        // Time in microseconds it takes for the cap to charge; at least 5x RC.
//                                            // 22 nF & 330R resistor RC = 7.25 us, times 5 = 36.3 us.
#define EC_TIMEOUT 2000                       // Timeout for the EC measurement in microseconds.

// Time scale to go from clock pulses to microseconds.
// 8 MHz clock: 8 = 2^3 pulses per microsecond, TIMESCALE 3.
#define TIMESCALE 3

#define I2C_DEFAULT 0x4c // The default used if no address found in EEPROM.

// The available I2C commands.
#define READ_EC               0x00            // Read the EC probe - produce 2 bytes of data (the cycle count).

// Other I2C paramenters.
#define MAX_TRANSMISSION 3                    // No more than three bytes in a single I2C transmission for this application, ever.
#define I2C_EEPROM  63                        // EEPROM address where our I2C slave address is stored.

uint8_t data[MAX_TRANSMISSION];               // Stores the incoming or outgoing I2C data.

// Advance declaration of callback functions.
void wireRequest(void);
void wireReceive(void);

volatile uint16_t dischargeCycles = 0;
volatile bool interrupted = false;

void setup() {

  //  TinyDebugSerial tinySerial= TinyDebugSerial();
  //  tinySerial.begin(38400);
  // Set up the timers
  TCCR0A = 0;
  TCCR0B = 0;
  TCCR0B |= (1 << CS01) | (1 << CS00);        // prescaler = 64 so 8 microseconds per tick at 8 MHz.

  TCCR1A = 0;                                 //  clear control register A
  TCCR1 = 0;                                  //  clear timer control register
  TCCR1 |= (1 << CS10);                       //  Set to no prescaler

  // Set up I2C interface and callback functions.
  TinyWireS.begin(I2C_DEFAULT);
  TinyWireS.onRequest(wireRequest);
  TinyWireS.onReceive(wireReceive);

  GIMSK |= (1 << PCIE);                       // Enable pin change interrupts.
  SREG |= (1 << 7);
}

void loop() {
  // Nothing to do here - everything is controlled by I2C commands.
}

/*
   Take a single reading from the EC probe.
*/
void readEC() {
  uint32_t totalCycles = 0;
  uint32_t startTime = 0;
  data[0] = 0;
  data[1] = 0;
  data[2] = 0;
  for (uint8_t i = 0; i < 64; i++) {

    // Stage 1: charge the cap, positive cycle.
    DDRB |= (1 << CAPPOS);                        // CAPPOS output.
    DDRB |= (1 << CAPNEG);                        // CAPNEG output.
    DDRB &= ~(1 << ECPIN);                        // ECPIN input.
    PORTB |= (1 << CAPPOS);                       // CAPPOS HIGH: Charge the cap.
    PORTB &= ~(1 << CAPNEG);                      // CAPNEG LOW.
    PORTB &= ~(1 << ECPIN);                       // ECPIN pull up resistor off.
    TCNT1 = 0;

    TCNT0 = 0;
    while (TCNT0 < (CHARGEDELAY >> 3)) {}

    // Stage 2: measure positive discharge cycle by measuring the number of clock cycles it takes
    // for pin CAPPOS to change from HIGH to LOW.
    dischargeCycles = 0;
    TCNT1 = 0;                                    // Reset the timer.
    DDRB &= ~(1 << CAPPOS);                       // CAPPOS input.
    DDRB |= (1 << ECPIN);                         // ECPIN output.
    PORTB &= ~(1 << CAPPOS);                      // CAPPOS pull up resistor off.
    PORTB &= ~(1 << ECPIN);                       // ECPIN LOW.
    PCMSK |= (1 << CAPPOS);                       // Set up the pin change interrupt on CAPPOS.
    interrupted = false;
    TCNT0 = 0;
    while (TCNT0 < (EC_TIMEOUT >> 3)) {
      if (dischargeCycles)
        break;
      if (interrupted)
        break;
    }
    PCMSK &= ~(1 << CAPPOS);                      // Clear the pin change interrupt on CAPPOS.
    if (interrupted) {
      data[0]++;  // Interrupt recorded.
    }
    else {
      data[1]++;  // Interrupt didn't happen - timeout.
      if ((PINB & (1 << CAPPOS)) == 0) {
        data[2]++; // No interrupt recorded but pin is low.
      }
    }

    totalCycles += dischargeCycles;

    // Stage 3: charge the cap, negative cycle.
    DDRB &= ~(1 << ECPIN);                        // ECPIN input
    DDRB |= (1 << CAPPOS);                        // CAPPOS output
    PORTB &= ~(1 << CAPPOS);                      // CAPPOS LOW
    PORTB |= (1 << CAPNEG);                       // CAPNEG HIGH: Charge the cap
    TCNT1 = 0;
    TCNT0 = 0;
    while (TCNT0 < (CHARGEDELAY >> 3)) {}

    // Stage 4: discharge the cap, compenstation cycle.
    DDRB &= ~(1 << CAPPOS);                       // CAPPOS input
    DDRB |= (1 << ECPIN);                         // ECPIN output
    PORTB |= (1 << ECPIN);                        // ECPIN HIGH

    // delay based on dischargeCycles
    TCNT1 = 0;
    TCNT0 = 0;
    if (dischargeCycles) {
      while (TCNT0 < ((dischargeCycles >> TIMESCALE) >> 3)) {}
    }
    else {
      while (TCNT0 < (CHARGEDELAY >> 3)) {}
    }
  }
  // Disconnect EC probe: all pins to INPUT.
  DDRB &= ~(1 << CAPPOS);                         // CAPPOS input
  DDRB &= ~(1 << CAPNEG);                         // CAPNEG input
  DDRB &= ~(1 << ECPIN);                          // ECPIN input
  PORTB &= ~(1 << CAPNEG);                        // CAPNEG pull up resistor off.
  PORTB &= ~(1 << ECPIN);                         // ECPIN pull up resistor off.

  uint16_t averageCycles = (totalCycles >> 6);
  //
  //  // Return the actual dischargeCycles in data[1] and data[2], useful for debugging and used for calibration.
  //  data[0] = 0;
  //  data[1] = (averageCycles >> 8) & 0xFF;
  //  data[2] = (averageCycles >> 0) & 0xFF;
  return;
}

ISR(PCINT0_vect) {
  interrupted = true;
//  dischargeCycles = TCNT1;
//  PCMSK &= ~(1 << CAPPOS);                      // Clear the pin change interrupt on CAPPOS.
}

void wireReceive(uint8_t n) {

  // Make sure we don't try to read more bytes than that fit in our data structure.
  if (n > MAX_TRANSMISSION)
    n = MAX_TRANSMISSION;
  for (uint8_t i = 0; i < n; i++) {
    if (TinyWireS.available())
      data[i] = TinyWireS.read();
    else
      break;
  }

  // Clear the buffer.
  // There should not be more data in the buffer than the already received bytes, unless the master
  // is misconfigured and sends more data than it should.
  while (TinyWireS.available())
    TinyWireS.read();

  // Series of if/else if is slightly smaller than switch/case statements.
  if (data[0] == READ_EC)
    readEC();

  // Any invalid commands are silently ignored.
}

void wireRequest() {
  TinyWireS.write(data[0]);
  TinyWireS.write(data[1]);
  TinyWireS.write(data[2]);
}

 

It's controlled over I2C:

 

#include <Wire.h>

// The available I2C commands.
#define READ_EC               0x00            // Read the EC probe - produce 2 bytes of data (the cycle count).
#define CALIBRATE_EC          0x02            // Set calibration of EC probe - comes with 2 bytes of data (value, pos).
#define GET_CALIBRATION       0x03            // Set calibration of EC probe - comes with 1 byte of data (pos).
#define CLEAR_CALIBRATION     0x04            // Remove a calibration point - comes with 1 byte of data (pos).

#define READ_NTC              0x10            // Read the NTC probe - produces 2 bytes of data (the ADC reading).
#define GET_NTC_R_NOMINAL     0X11            // Get the nominal resistance value of the NTC (in Ohm).
#define GET_NTC_TEMP_NOMINAL  0x12            // Get the nominal temperarture value of the NTC (in deg C).
#define GET_NTC_BCOEFFICIENT  0x13            // Get the beta coefficient value of the NTC.
#define GET_NTC_R_SERIES      0x14            // Get the series resistor value (in Ohm).

#define SET_ADDRESS           0x20            // Set the I2C address of this device - comes with 1 byte of data (the address).


#ifdef ESP8266
/* BEGIN OTA (part 1 of 3) */
#include <ArduinoOTA.h>
const char* ssid = "Squirrel";
const char* password = "AcornsAreYummie";
/* END OTA (part 1 of 3) */
#endif

uint32_t currentMillis = 0;
uint8_t address = 76;
uint8_t data[3];

void setup() {

  Serial.begin (115200);

#ifdef ESP8266
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

  Serial.println('\n');
  Serial.print("Connected to ");
  Serial.println(WiFi.SSID());              // Tell us what network we're connected to
  Serial.print("IP address:\t");
  Serial.println(WiFi.localIP());           // Send the IP address of the ESP8266 to the computer

  /* BEGIN OTA (part 2 of 3) */
  ArduinoOTA.setHostname("ESP8266");
  ArduinoOTA.setPassword("esp");

  ArduinoOTA.onStart([]() {
    Serial.println("Start");
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });
  ArduinoOTA.begin();
  Serial.println("OTA ready");
  /* END OTA (part 2 of 3) */
#endif

  Wire.begin();
  Serial.println("scanning for devices....");
  scanBus();
  Serial.println();
//  calibrateEC(0.2, 0);
//  getCalibration(0);
  Serial.println();

  currentMillis = millis();
}  // end of setup


/***************************************************************************/
void loop() {
#ifdef ESP8266
  /* BEGIN OTA (part 3 of 3) */
  ArduinoOTA.handle();
  /* END OTA (part 3 of 3) */
#endif

  if (millis() - currentMillis > 2000) {
    scanBus();
    currentMillis = millis();

    Wire.requestFrom(address, (uint8_t)3);
    for (int i = 0; i < 3; i++) {
      data[i] = Wire.read();
      Serial.print(data[i]);
      Serial.print(" ");
    }
    Serial.println();
    readEC();
  }
}
/***************************************************************************/


void scanBus() {
  byte count = 0;
  String line = "";
  for (byte i = 1; i < 120; i++)
  {
    Wire.beginTransmission (i);
    if (Wire.endTransmission () == 0)
    {
      line += "Found address: ";
      line += String(i, DEC);
      line += " (0x";
      line += String(i, HEX);
      line += ")\n\r";
      count++;
      delay (1);  // maybe unneeded?
    } // end of good response
  } // end of for loop

  Serial.println ();
  Serial.println ("Done.");
  Serial.print ("Found ");
  Serial.print (count, DEC);
  Serial.println (" device(s).");
  Serial.println (line);
}

void readNTC() {

  Wire.beginTransmission(address);
  Wire.write(READ_NTC);
  Wire.endTransmission();
  delay(10);
  Wire.requestFrom(address, (uint8_t)3);
  for (int i = 0; i < 3; i++) {
    data[i] = Wire.read();
  }
  uint16_t result = (data[0] << 8) | data[1];
  Serial.print("Measured temperature: ");
  Serial.print((float)result / 100);
  Serial.println("°C.");
}

void getCalibration(uint8_t pos) {

  if (pos < 8) {
    Wire.beginTransmission(address);
    Wire.write(GET_CALIBRATION);
    Wire.write(pos);
    Wire.endTransmission();
    delay(20);
    Serial.print("Read back calibration data: ");
    Wire.requestFrom(address, (uint8_t)3);
    for (int i = 0; i < 3; i++) {
      data[i] = Wire.read();
      Serial.print(data[i]);
      Serial.print(" ");
    }
    Serial.println();

    Serial.print("EC value for this data point: ");
    Serial.println((float)data[0] / 32, 2);
    Serial.print("Discharce cycles: ");
    Serial.println((data[1] << 8) | data[2]);
  }
  else {
    Serial.print("Invalid position: ");
    Serial.println(pos);
  }
}

void calibrateEC (float EC, uint8_t pos) {

  uint8_t value = EC * 32;
  Serial.print("Ordering calibration for EC = ");
  Serial.print(EC, 2);
  Serial.print(", value = ");
  Serial.print(value);
  Serial.print(", to be stored at EEPROM position ");
  Serial.println(pos);
  Wire.beginTransmission(address);
  Wire.write(CALIBRATE_EC);
  Wire.write(value);
  Wire.write(pos);
  Wire.endTransmission();
  delay(20); // wait for measurement to complete.
  getCalibration(pos);
  Serial.println("Calibration complete.");
}

void readEC() {
  Wire.beginTransmission(address);
  Wire.write(READ_EC);
  Wire.endTransmission();
  for (int j=0; j<8; j++) {
    Serial.print("Requested EC reading attempt ");
    Serial.print(j),
    Serial.print(", received: ");
    Wire.requestFrom(address, (uint8_t)3);
    for (int i = 0; i < 3; i++) {
      data[i] = Wire.read();
      Serial.print(data[i]);
      Serial.print(" ");
    }
    Serial.println();
    Serial.print("Discharce cycles: ");
    uint16_t cycles = (data[1] << 8) | data[2];
    Serial.println(cycles);
  }
//  Serial.print("Measured EC value: ");
//  Serial.println((float)data[0] / 32);
}

 

Output on the serial monitor with J1 open (first value is number of interrupts received; second is number of times the loop timed out; third is number of times PB1 was low after the timeout).

 

Done.
Found 1 device(s).
Found address: 76 (0x4c)
 
0 0 0  
Requested EC reading attempt 0, received: 0 64 0  
Discharce cycles: 16384
Requested EC reading attempt 1, received: 0 64 0  
Discharce cycles: 16384
Requested EC reading attempt 2, received: 0 64 0  
Discharce cycles: 16384
Requested EC reading attempt 3, received: 0 64 0  
Discharce cycles: 16384
Requested EC reading attempt 4, received: 0 64 0  
Discharce cycles: 16384
Requested EC reading attempt 5, received: 0 64 0  
Discharce cycles: 16384
Requested EC reading attempt 6, received: 0 64 0  
Discharce cycles: 16384
Requested EC reading attempt 7, received: 0 64 0  
Discharce cycles: 16384

 

So as expected no interrupts and PB1 is still high at the end of the discharge cycle.

 

Now with a 1k resistor across J1:

 

Done.
Found 1 device(s).
Found address: 76 (0x4c)
 
0 64 0  
Requested EC reading attempt 0, received: 0 64 64  
Discharce cycles: 16448
Requested EC reading attempt 1, received: 0 64 64  
Discharce cycles: 16448
Requested EC reading attempt 2, received: 0 64 64  
Discharce cycles: 16448
Requested EC reading attempt 3, received: 0 64 64  
Discharce cycles: 16448
Requested EC reading attempt 4, received: 0 64 64  
Discharce cycles: 16448
Requested EC reading attempt 5, received: 0 64 64  
Discharce cycles: 16448
Requested EC reading attempt 6, received: 0 64 64  
Discharce cycles: 16448
Requested EC reading attempt 7, received: 0 64 64  
Discharce cycles: 16448

 

So now still no interrupts received, but every time the pin PB1 was low at the end of the discharge cycle. I expected to see 64 0 0 on each line.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

wvmarle wrote:
I try to time the discharge time of a capacitor.

 

Then I would expect a resistor parallel to capacitor through which the cap discharges.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You have to image a resistance at the J1 pins., the discharge occurs at " // Stage 2: " when EC is set low. (CAPNEG is still low)


I thought that the 1 uA (max) input leakage current would be the problem, but that would require the J1 resistance to be >1.5 Megohm.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

 

Wouldn't jumping J1 short out the power supply?   How does that work?

 

Jim