Timer based software i2c?

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

Hi!

My Atmega644 communicates via the hardware twi-interface with other CPUs. Other slaves, such as temperature probes (LM75) and digital potentiometers are reached via software i2c, i.e on two normal cpu pins.

The problem is that when I need communication on the software i2c, the cpu is "stuck" until it returns from the communication. My other tasks are put on hold.

The communication on the software i2c is not time critical, I ask for temperatures once every second.

Is there any sample code for a software i2c solution that is timer based, or interrupt based? All code I have seen is of the init-and-wait kind.

Best regards,

/Bo

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

Any reason not to have other slaves on the same hardware TWI bus like the other cpu?

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Yes, I want to isolate critical communication with other CPUs from "lower priority" information.

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

Since I2C devices without µC make no SCL stretching, a whole I2C packet should need only below 1msec.
If this very small time was critical in your mainloop, maybe you should rethink your program flow.

Peter

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

The problem is that the temperature probes are located quite far away (20 cm wiring), thus requiring their own ESD protection, making fast communication impossible. There are visible shark fins on the SCL and SDA lines, even in 10ms window.

IF the communication were to take just 1ms, I wouldn't have a problem.

/Bo

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

As I understand you have a hardware TWI bus with another AVR on it. And a software i2c bus with several LM75 sensors on it.

Your Master polls the LM75's every second. Your Master may be interrupting on its TWI bus during the software i2c execution.

I see no problem with the LM75's getting uneven SCL clocks due to an IRQ being serviced.

I would not advise the software i2c being invoked from within a Timer IRQ in the first place, but it should not take more than 100us per primitive i2c operation. So you either do all 6 or 7 ops to read the temperature in one go, or do one op per Timer IRQ.

If your software i2c is polled from the foreground, it can be interrupted as much as you like.

David.

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

David, spot on.

The hardware TWI gets higher prio since it is IRQ-based. The software I2C is timer-invoked from the main while(1) loop. I don't care if each primitive SW-I2C operation takes place even 1ms apart, as long as they don't interfere with other tasks.

The timer IRQ just sets flags which the while(1) observes, so TWI should be affected minimally.

My question was if anyone had implemented anything like this before.

/Bo

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
volatile uint8_t TWI_ready;
volatile uint8_t please_start_i2c;

void main()
{
    ...
    while (1) {
        if (TWI_ready) process_TWI_data();
        if (please_start_i2c) temp = read_LM75();
        ...
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MrMayhem wrote:
The problem is that the temperature probes are located quite far away (20 cm wiring), thus requiring their own ESD protection, making fast communication impossible. There are visible shark fins on the SCL and SDA lines, even in 10ms window.

Mean you 20cm near or 20km far?

10ms sounds extremely long, which pullup use you?
The I2C drive up to 3mA, so 1.8k pullup looks nice.

Peter

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

David, the problem is not that TWI needs time, the TWI gets its time, since it is IRQ-based. Messages are processed and the communication (ring)-buffers are filled.

THe problem is that I have other tasks in the while(1). For instance 10ms tasks and 100ms tasks that processes the information in the TWI-buffers and empties them as each message is processed. These wont be performed if the cpu is waiting for sw-i2c.

Peter: it is 20cm, heavily protected by ESD-diods and PTC-resistors. The pull-ups are 10k.

/Bo

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

Surely your IRQ code processes stuff swiftly, and the foreground code does not really matter how long it takes.

You can always do an op at a time.

    while (1) {
         if (please_svc_i2c) {
              please_svc_i2c--;
              do_next_i2c_primitive();
         }
         ...
     }

If you are really tight for processing time, you could just process one i2c bit in every Timer ISR(). i2c has no lower speed, although some devices may decide that their Master may have crashed.

I would guess that you are using 100kHz i2c bus. So 9 bits are going to take 90us.

Perhaps you could explain how many things you are trying to service and what throughput you hope to achieve.

David.

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

MrMayhem wrote:
Peter: it is 20cm, heavily protected by ESD-diods and PTC-resistors. The pull-ups are 10k.

I know, supressor diodes are big capacitors (several 1000pF), thus I prefer normal diodes against GND and VCC to protect data lines.

10k are to high, 1.8k will increase the speed over 5 times.

Also you can count the bytes and transmit only a single byte instead the whole packet on every main loop.

Peter

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

Or handle just one bit at a time on each main loop iteration.

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

David: I'm nowhere near 100kbps because of my heavy ESD protection. One byte takes 500 µs.

danni: I can't really do anything about the electonic circuitry as of now, but in an upcoming revision I will suggest altering the ESD-protection.

jayjay: That is my thought. Like this:

[0x00, 0x10, 0x11, 0x00, ..., 0xFF, ...]

The two bits are SCL and SDA respectively. I can write things on the SW-I2C bus by populating this array, including the I2C_START, ADDRESS, MESSAGE and finally I2C_STOP. The 0xFF ends the write task and opens up for new communication.

Thanks for all your input.

/Bo

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

I believe that the bus should be ok with the max capacitance of 400pF. Have you looked at the SDA line with an oscilloscope. The -ve transitions should look quite clean but the +ve transitions will have a slow rise time. 1k8 resistors will definitely help. Look at the spec. You may be able to go a little lower, or use a bus driver chip.

Yes. You can always just do one primitive op at a time. With a counter or a state table.

David.

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

Yes, David. I have looked at the SCL and SDA line all day. They are sharkfins, to say the least. Slow rising, fast falling. I'll try to convince the hardware guys to ease up on the ESD, but that might require another day at the ESD test facility.

By trimming the delays, I am down to 2.5ms for my three software i2c communications per second. At least my 10ms tasks are always invoked.

I'll have a go at "primitivizing" the software i2c at a later stage. Thanks for everyone's input!

Regards,

/Bo