Infraviolet
Posts: 22
Joined: Wed Jan 30, 2019 10:47 pm

BCM2835 library, I'm after 1 to 20 microsecond delays but needn't be very accurate

Sun May 05, 2019 10:35 pm

I'm running a collection of shift register from a pi. I need to clock data into them and want to get this whole operation done in less than a millisecond. I don't need great accuracy but need to have delays atleast 1uS long and ideally less than 10uS long, less than 10uS long is pretty essential. I execute these delays between toggling GPIO pins and there are about 50 such delays involved in the sequence of actions needed to write to my register bank. For shorter delays than 1uS I would be at risk of the shift register not seeing the signals properly (datasheet says ideally not to feed in at >1MHz), for longer delays substantially longer than 20uS I'm getting close to spoiling my hope of getting the setting of the register bank all done in under 1ms. I stress than accurate timing isn't critical, just creating a delay which is always between the upper (20uS but ideally 10uS) and lower (1uS) time limits.I can cope if it occasionally takes longer than 20uS but don't want it to be always, or often, taking 80uS or some other time period >> 10uS.

I use the bcm2835 library for all my GPIO stuff and it works well, I certainly can't change library and start using pigpio or wiringpi at this point, I've got far too much stuff working perfectly in bcm2835. I know the bcm2835 library does a microseconds delay function but it apparently gives a whole 80uS of delay when told to give a zero uS delay, so it can't do 1 to 20uS delay times.

I've heard about busy waits but am not sure quite what these are. I've also heard mentions of micro and nano sleep functions but have seen warnings about them not working well at all. I would wonder about doing a pointless iteration of a while loop with a few instructions on each cycle of it, but can't be sure how long that would actually take and whether, as the Pi's non-realtime raspbian operating system shifts between executing different processes, any such attempt to work this out would become futile if different amounts of background tasks were running on the pi at the time.

Thanks

User avatar
joan
Posts: 13917
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: BCM2835 library, I'm after 1 to 20 microsecond delays but needn't be very accurate

Sun May 05, 2019 11:16 pm

Your best bet would be to use SPI to read/write the shift registers. On a Pi3B+ I can read a chain of 7 at a rate of 3400 reads per second from Python.

Infraviolet
Posts: 22
Joined: Wed Jan 30, 2019 10:47 pm

Re: BCM2835 library, I'm after 1 to 20 microsecond delays but needn't be very accurate

Mon May 06, 2019 3:18 pm

The shift registers I write to aren't SPI devices. They don't have MISO, MOSI,CSEL... pins. They just have a serial in pin, a clock pin and an enable pin. They take data according to the attacehd timing diagram. They work well with bit banging but right now my bangs are based on a minimum timeable interval of 1ms during testing. I need to get that interval down to the 1uS to 10uS range.

https://protostack.com.au/wp-content/up ... ter_10.jpg

User avatar
mikronauts
Posts: 2698
Joined: Sat Jan 05, 2013 7:28 pm
Contact: Website

Re: BCM2835 library, I'm after 1 to 20 microsecond delays but needn't be very accurate

Mon May 06, 2019 3:57 pm

The diagram suggests that using an inverted CSEL as ST_CP, CLK & MOSI should work for your shift register.
Infraviolet wrote:
Mon May 06, 2019 3:18 pm
The shift registers I write to aren't SPI devices. They don't have MISO, MOSI,CSEL... pins. They just have a serial in pin, a clock pin and an enable pin. They take data according to the attacehd timing diagram. They work well with bit banging but right now my bangs are based on a minimum timeable interval of 1ms during testing. I need to get that interval down to the 1uS to 10uS range.

https://protostack.com.au/wp-content/up ... ter_10.jpg
http://Mikronauts.com - home of EZasPi, RoboPi, Pi Rtc Dio and Pi Jumper @Mikronauts on Twitter
Advanced Robotics, I/O expansion and prototyping boards for the Raspberry Pi

User avatar
joan
Posts: 13917
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: BCM2835 library, I'm after 1 to 20 microsecond delays but needn't be very accurate

Mon May 06, 2019 4:18 pm

Mine aren't SPI devices either. I'm using SN74HC165N chips.

All they need is a clock to shift the data. I connect a spare GPIO to the load data pin. The final chip's output bit is connected to SPI MISO. The first chip's clock bit is connected to SPI CLK. I don't connect SPI CS or SPI MOSI.

To take a reading I toggle the load data pin to load the bits. I then transfer 7 bytes by SPI. The SPI hardware provides the clocks and reads the data back along MISO.

Python code to take a reading.

Code: Select all

def read(self):
   self._pi.write(self._SH_LD, 0)
   self._pi.write(self._SH_LD, 1)
   tnow = time.time()
   count, data = self._pi.spi_read(self._h, self._chips)
   if data != self._last_data:
      for i in range(self._chips):
         if data[i] != self._last_data[i]:
            for j in range(8):
               if (data[i] & (1<<j)) !=
                  (self._last_data[i] & (1<<j)):
                  print((i*8)+j, (data[i]>>j)&1, tnow)
      self._last_data = data

Infraviolet
Posts: 22
Joined: Wed Jan 30, 2019 10:47 pm

Re: BCM2835 library, I'm after 1 to 20 microsecond delays but needn't be very accurate

Wed May 08, 2019 1:18 am

Are you saying to try using Pi pin (physical pin layout) 23 as SHCP and pin 19 as the SERIAL line to the shift register which is acting as my extra outputs? The use any spare GPIOs as the latch control, so I can twiddle the latch control GPIO as a bit bang, then send as many bytes worth of SPI as necessary to clock in the state for all my shift register outputs, then use the GPIOS again to enable the outputs? In my situation it is very important that the serial line is in the high or low state as desired when the clock has it's rising edge, according to the order outliend below:
1.Set serial to desired high or low
2.wait a "while"
3.now raise SHCP
4.wait another while
5.now lower SHCP
6.serial can now be changed, or not depending if the next bit is low or high, serial does not require any kind of "return to zero". In cases where many 1's are sent after each other it just stays high without moving, in cases of many zeroes it stays low.

Would SPI ensure this order?

I'm thinking that as data won't leave the last shift register's output until after the whole message is sent* there is no point in connecting the Pi's MISO pin?

Thanks

P.S. I haven't used python recently so my memory is a bit rusty, but as far as I can tell the example you provided is mainly just a discussion of the bit and byte manipulation, the actual details of the SPI are all contained within self._pi.spi_read() ? Or is there something else I should notice?

*I am using the shift register solely as an extra bunch of GPIO outputs, not as inputs at all and nor do I plan to need such extra inputs in my present project

User avatar
joan
Posts: 13917
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: BCM2835 library, I'm after 1 to 20 microsecond delays but needn't be very accurate

Wed May 08, 2019 7:14 am

Yes SPI will work..

Connect SPI CLK to the clock input of the first chip and daisy chain the rest.

Connect a GPIO to the first chip's shift/write equivalent and daisy chain the rest.

Connect SPI MOSI to the bit input of the first chip and daisy chain the output bit to the next chips input bit.

Initialise the shift/write pin to shift.

Write x bytes of SPI (one per chip if they are 8 bits each).

Pulse the shift/write pin to write momentarily.

Repeat.

Infraviolet
Posts: 22
Joined: Wed Jan 30, 2019 10:47 pm

Re: BCM2835 library, I'm after 1 to 20 microsecond delays but needn't be very accurate

Tue May 21, 2019 7:13 pm

I did some further tests and found that while the bcm2835 library says a 0 delay results in 80ms I ran some tests under light and medium CPU loads, my whole chain of pulses was, according to an oscilloscope, able to, with bit banging and no need for SPI, complete in under 200ms. I used bcm2835_delayMicroseconds(1); to achieve this. I guess the bcm2835 library's 80us figure was just talking worst cases scenarios where an extreme CPU load is induced by other programs running at the same time.

Return to “C/C++”