I have designed a small circuit that will convert the 24vac to ~3.3 dc with acceptable ripple. By acceptable ripple I mean that it never goes low enough to trigger an edge detect on a Raspberry Pi 3b+ gpio pin. Here is the circuit:
I can run SPICE on this in OrCAD Capture CIS Lite and I get the following output:
Now when I run this with my breadboard, I get a different waveform but I'll get to that later.
For my test, I have a Raspberry Pi 3b+. I have a Adafruit MCP3008 8-Channel 10-Bit ADC With SPI Interface for Raspberry Pi that I will use to read the voltage on GPIO pin 25 Pin 25 is initialized as a input GPIO with both rising and falling edge detects. I use GPIO 23 as an output to turn a relay on to supply 24vdc to my rectified circuit.
I run the following code:
Code: Select all
#!/usr/bin/env python2.7 ## on esp import RPi.GPIO as GPIO import time from datetime import datetime from datetime import timedelta from time import sleep # this lets us have a time delay (see line 12) state = 0 lastrise = None lastdrop = None starttime = 0 AO_pin = 0 #flame sensor AO connected to ADC chanannel 0 # change these as desired - they're the pins connected from the # SPI port on the ADC to the Cobbler SPICLK = 11 SPIMISO = 9 SPIMOSI = 10 SPICS = 8 RELAY = 23 OPTO1 = 25 linerf =  def my_callback(channel): global linerf global starttime global lastrise global lastdrop global state global AO_pin global SPICLK global SPIMISO global SPIMOSI global SPICS # time.sleep(0.0001) nowtim = datetime.utcnow() gpiolevel = GPIO.input(OPTO1) # ad_value = readadc(AO_pin, SPICLK, SPIMOSI, SPIMISO, SPICS) # voltage = ad_value*(3.3 / 1024) # *5 no voltage divider here voltage = 1.11 measuretime = datetime.utcnow() - nowtim timediff = None if gpiolevel: # if port 25 == 1 # if lastrise: # timediff = nowtim - lastrise # lastrise = nowtim # if (timediff and # timediff.days == 0 and # timediff.seconds == 0 and # timediff.microseconds < 1000): # return linerf.append([ nowtim, voltage, state + .2, 1, measuretime ]) # lastdrop = None else: # if port 25 != 1 # if lastdrop: # timediff = nowtim - lastdrop # lastdrop = nowtim # if (timediff and # timediff.days == 0 and # timediff.seconds == 0 and # timediff.microseconds < 1000): # return linerf.append([ nowtim, voltage, state + .2, 0, measuretime]) # lastrise = None return #port init def init(): GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) # set up the SPI interface pins GPIO.setup(SPIMOSI, GPIO.OUT) GPIO.setup(SPIMISO, GPIO.IN) GPIO.setup(SPICLK, GPIO.OUT) GPIO.setup(SPICS, GPIO.OUT) GPIO.setup(OPTO1, GPIO.IN) # set GPIO25 as input (button) GPIO.setup(RELAY, GPIO.OUT) # set GPIO24 as output GPIO.output(RELAY, False) # when a changing edge is detected on OPTO1 port, regardless of whatever # else is happening in the program, the function my_callback will be run GPIO.add_event_detect(OPTO1, GPIO.BOTH, callback=my_callback) pass #read SPI data from MCP3008(or MCP3204) chip,8 possible adc's (0 thru 7) def readadc(adcnum, clockpin, mosipin, misopin, cspin): if ((adcnum > 7) or (adcnum < 0)): return -1 GPIO.output(cspin, True) GPIO.output(clockpin, False) # start clock low GPIO.output(cspin, False) # bring CS low commandout = adcnum commandout |= 0x18 # start bit + single-ended bit commandout <<= 3 # we only need to send 5 bits here for i in range(5): if (commandout & 0x80): GPIO.output(mosipin, True) else: GPIO.output(mosipin, False) commandout <<= 1 GPIO.output(clockpin, True) GPIO.output(clockpin, False) adcout = 0 # read in one empty bit, one null bit and 10 ADC bits for i in range(12): GPIO.output(clockpin, True) GPIO.output(clockpin, False) adcout <<= 1 if (GPIO.input(misopin)): adcout |= 0x1 GPIO.output(cspin, True) adcout >>= 1 # first bit is 'null' so drop it return adcout def sortbytimekey(x): global starttime mstime = x - starttime key = mstime.seconds + mstime.microseconds / 1000000.0 return key def main(): init() global linerf global starttime time.sleep(2) voltimelist =  sleeptime = 0.00002 # .02 ms global state # 0 = not started, 1 = on, 2 = off, 3= zero reached avgvolt = 0 avgvoltcnt = 0 maxvolt = 0 minvolt = 99999 testtime = 2 # seconds voltage = 0 # initial voltage value print ("will detect voltage. ") starttime = datetime.utcnow() measuretime = datetime.utcnow() - starttime voltimelist.append([datetime.utcnow(), 0.0, state, GPIO.input(OPTO1), measuretime]) GPIO.output(RELAY, True) state = 1 print("ON, state = " + str(state)) timercount = int(testtime / sleeptime) + 1 while timercount >= 0 or state < 3: timercount -= 1 if timercount == 0: GPIO.output(RELAY, False) state = 2 print("OFF, state = " + str(state)) time.sleep(sleeptime) readtime = datetime.utcnow() ad_value = 0 + readadc(AO_pin, SPICLK, SPIMOSI, SPIMISO, SPICS) voltage = ad_value*(3.3 / 1024) # *5 no voltage divider here thistime = datetime.utcnow() measuretime = thistime - readtime if state == 2 and voltage <= 0.3: print ("almost zero detected = " + str("%.4f"%voltage) + ", at time " + thistime.strftime("%H:%M:%S.%f")) state = 3 voltimelist.append([thistime, voltage, state, GPIO.input(OPTO1), measuretime]) if voltage > 0.5: avgvolt = ((avgvoltcnt * avgvolt) + voltage) / (avgvoltcnt + 1) avgvoltcnt += 1 if voltage > maxvolt: maxvolt = voltage if voltage < minvolt: minvolt = voltage pass print ("Time's up. Finished! Average volts=" + str("%.4f"%avgvolt) + ", Max volts = " + str("%.4f"%maxvolt) + ", Min volts = " + str("%.4f"%minvolt) + " , Count = " + str(avgvoltcnt) + ", state = " + str(state)) print "voltimelist len =", len(voltimelist) file = open("voltgraph.csv", "w") voltimelist = voltimelist + linerf starttime = voltimelist voltimelist.sort(key = sortbytimekey) for voltim, volts, state, pin, measuretime in voltimelist: mstime = voltim - starttime file.write( "%d"%mstime.seconds + ".%06d"%mstime.microseconds + ", " + str(state) + ", " + str("%.4f"%volts) + ", " + str(pin) + ",%d"%measuretime.seconds + ".%06d"%measuretime.microseconds + ", " + voltim.strftime("%H:%M:%S.%f") + "\n" ) file.close() if __name__ =='__main__': try: main() except KeyboardInterrupt: pass GPIO.cleanup()
- 1. Initialize the GPIO pins and set up GPIO.BOTH edge detection on pin 25 to call my callback routine.
- 2. I close the relay, energizing my rectifier and supplying rippling ~ 3.0 v to the GPIO Pin 25. However, the ripple does not go low enough to trigger a falling edge
- 3. When the callback occurs, I note the time and read the GPIO pin 25. I add these values to a python list where I am logging events.
- 4. The relay is closed for about 2 seconds. The python code loops with a .02 ms wait between loops. At each iteration of the loop, the voltage is read, the GPIO pin is read and the time is noted. These items are added to a python list where I am logging events.
- 5. When the 2 seconds are up the relay is opened but the looping continues until the voltage on pin 25 drops to less that 0.3 volts
- 6. Once the 0.3 voltage is reached, the pyhon event list is written to a file where I can us MS Excel to graph it.
- 1. The first edge is detected at about 1.5 v. However, when I read the GPIO pin, it still reads ON.
- 2. I continue getting edge detections about every 0.4 ms and I can see the voltage dropping but the GPIO pin still reads ON until the voltage reaches about 1.2v.
- 3. At about 1.2v I start reading the GPIO pin off but am still getting edge detections until about 0.7 v.
My next experiment will be to try a Schmitt Trigger on the output of my rectifier. My thought is that this will make the rise and fall steep enough to avoid this issue.
I'd like any suggestion anyone might have about how I can make the voltage fall steeper. I've tried different capacitors and resistors but can't seem to get the results I need.
PS. I have other diagrams and graphs but can't figure out how to attach them. If anyone is interested, I'll attach them to a different response.