RPI I2C interface to Microchip embedded uP – Clock stretching

If you are going to implement I2C to an embedded uP read this first http://www.slate.com/blogs/bad_astronomy/2016/03/28/psychedelic_stroboscopic_easter_eggs.html

If you are using a Microchip uP you might want to continue reading.

Here is the problem, Raspberry Pi’s I2C software can’t cope with slave clock stretching, not a problem if you can service the data request quickly, well you would have thought not anyway. Unfortunately Microchip’s hardware (using a PIC18F14K50 and many others)  always puts in a small clock stretch for a slave transmit, even if you disable clock stretching with the SEN bit.   A thorough read of the data sheet gives you a clue “The ACK pulse will be sent on the ninth bit and pin SCK/SCL is held low regardless of SEN“.

So data transmission TO the PIC works fine (if you can deal with the I2C data quickly enough), but for Slave data transmit TO the RPI you get errors. The problem is, they are random and depend on the exact timing of the I2C bus and uP speed.

This clock stretch only happens after the address byte and before the transmission data. It causes a short or missing clock pulse (as the RPI ignores the presence of the clock held low by the slave) as in the transition of bytes 3 &4  of data in the oscilloscope capture below.

DS1Z_QuickPrint7

So how do we work around this, well to be honest there isn’t a total solution. (that I’ve found) the best that I have achieved is to change the I2C clock speed  so the timing of a clock stretch happens when the clock is already low and tweak the uP interrupt software.

The clock speed change is unfortunately a trial and error process whilst monitoring the data (and probably watching with a scope). To change the I2C bus speed with a newer PI distro, you need to edit the /boot/config.txt and edit or add the line “dtparam=i2c1_baudrate=clockspeed” try clock speeds from 20000 to 400000 and follow by a reboot of the PI to make the changes active.

The bus clock speed that will work will vary with the microprocessor speed,  so there is no single solution. With my setup 200Khz and 50Khz works well (uP clock @32Mhz) where 400khz and 100khz is a total wright off.

I have also changed the I2C code in the PIC18F14K50 to give a fast set of the  BF flag after data transmission which helps minimise the clock hold time.

if (PIR1bits.SSPIF) {
      
        if (!SSPSTATbits.D_NOT_A) {
            //
            // Slave Address
            //
            i2c_byte_count = 0;

            if (SSPSTATbits.BF) {
                // Discard slave address
                sspBuf = SSPBUF;    // Clear BF
                SSPSTATbits.BF=1;
            }

            if (SSPSTATbits.R_NOT_W) {
                // Reading - read from register map
                SSPCON1bits.WCOL = 0;
                SSPBUF           = i2c_reg_map[i2c_reg_addr++];
              
            }

        } else {
            //
            // Data bytes
            //
            i2c_byte_count++;

            if (SSPSTATbits.BF) {
                sspBuf = SSPBUF;    // Clear BF
                
            }

            if (SSPSTATbits.R_NOT_W) {
                // Multi-byte read - advance to next address
                SSPCON1bits.WCOL = 0;
                SSPBUF           = i2c_reg_map[i2c_reg_addr++];
                SSPSTATbits.BF=1;
               
            } else {

                if (i2c_byte_count == 1) {
                    // First write byte is register address
                    i2c_reg_addr = sspBuf;
                } else {
                    // Write to register address - auto advance
                    //   to allow multiple bytes to be written
                    i2c_reg_map[i2c_reg_addr++] = sspBuf;
                }
            }
           
        }//else
        
        SSPCON1bits.CKP = 1;            // Release clock
        // Limit address to size of register map
        i2c_reg_addr %= sizeof(i2c_reg_map);

        // Finally
        PIR1bits.SSPIF  = 0;            // Clear MSSP interrupt flag
      
    }   

With these changes, I have got (as the adverts say) up to 100% TX from a slave without error. This is about the best we can do until either Microchip change their hardware, or RPI write a I2C handler that supports clock stretch.

 

Nottingham Gaussfest 2016

My Coils, static machines and Twin PiZero TeslaCoils

An amazing day, all my coils and static machines worked from beginning to end with no issues. The VDG performed well after a hail storm had knocked out all of the moisture from the air. It made a huge difference. I did however have a failure the night before the Gaussfest (therefore it cant count as a failure AT the Gaussfest) where I shared the earth from my VDG with the PiZero coils. A strong discharge killed the i2c on my Pi Zero. A swap of PiZeros, a number of downloads and a recompile got me back working in a hour or so. Glad I’d gone with the PIZero saved me £21 over a full Pi Failure.

 

Roger’s VDG

Roger was new to the Gaussfest and brought his commercial VDG, a very nice unit with LOADS of accessories. It ran fairly well during the day after he replaced the original 15year old+ belt. I suspect he suffered with the damp as well, but it didn’t affect his VDG as much as mine, I put this down to a lack leakage from his very smooth top terminal. (The VDG’s not his).

 

Steve’s coils

 

Steve brought a couple of coils and a VDG (sorry no photo) . His desktop Static gap coil was a good solid performer, but his VTTC was just a work of art. It performed well with those lovely straight arcs characteristic of VTTC’s. He vows to return to Cambridge, can’t wait.

 

Jason’s Coil

Jason’s coil ran very well, until he had a capacitor failure, which was a great shame, but hopefully easy to rectify.

Daves coil

Dave’s coil ran well as usual. Superb looking and a very reliable performer. I know Dave has plans for an upgrade, so look forward to the MkII

 

Phil & Phil’s coils


Slow motion (90fps capture)

Phil and Phils coils (now share so many parts I can’t tell them apart, I’m not sure their owners can either). Both coils ran very well giving 8-10′ arcs to the floor,ceiling and occasionally to a target earth. PhilS did have a problem with a stray topload cable that caused a secondary strike

DSC_1425

It didn’t appear to have done much damage, but only a strip down will tell.

 


Thanks to everyone that came and especially those who brought “stuff” to demonstrate. After talking to a couple of non-UK visitors they are very envious of our Teslathons, there are very few across the world, and the UK has two!

DSC_1323

See you all at the next Gaussfest or at Cambridge.

 


Other Photos / links from the event.

Steve Lane

https://plus.google.com/u/0/photos/+SteveLane/albums/6258914846725227377

 

Strontium breakouts

A test of breakout points made almost entirely of Strontium. The idea is that rather than containing the Strontium in a tube that needs to withstand the heat of an arc, we make a breakout with as much Strontium as possible. Of course Strontium is quite a good insulator so we need to add in a conductive component and something to hold it all together. This test uses PVC glue as the binder and bear conductive ink as the conductor.

tmp_24485-20160117_1901352034523555tmp_24485-20160117_1857471367784658tmp_24485-20160117_185517775580088tmp_24485-20160117_185414-1425974767

Initial tests on a large rotary classic tesla coil

DSC_1015DSC_1013DSC_1005DSC_1263_NEF_embedded

 

Some effect, but not as strong as Id hoped. Although the one on the chicken stick wasn’t bad.

SSTC 1Kw Much better results.

 

DSC_1097 DSC_1109 DSC_1111 DSC_1116

A great improvement on any other methods that I have used, and better still, the breakouts seem to be quite resilient and can be used multiple times.

Time to try other mixes 🙂