Saturday, November 5, 2016

Arduino 4-20 mA input

This is a quick discussion of how to feed a 4-20 mA signal into an Arduino. Looking for 4-20 mA output from an Arduino? See here.

I bought a pressure transmitter off of ebay that outputs a 4-20 mA current signal, because I like to live it up. The 4-20 mA current is very common in industrial control systems, so it's relatively easy to find various transmitters with this output. However, an Arduino can't natively read a current signal with its analog input pins - they measure voltage. We need to convert this current signal to a voltage. Fortunately, this is a piece of cake to do with a simple circuit.


Precious peppy pressure


The transmitter I bought is a Setra 209 model (datasheet here). It takes a 9-30V input, and acts as a current controller to put out a 4 to 20 milliamp signal proportional to the pressure it senses, with a span of zero to 100 psig. Plotting it out:



We can use a simple resistor circuit to generate a voltage readable to the Arduino that is proportional to the current. The Arduino AnalogRead function gives a 0-1023 value output proportional to the measured voltage on the analog input pin, with 0 corresponding to 0V or Ground (duh) and 1023 corresponding to the reference voltage (5V for the plain jane Arduino if nothing's connected to the Aref pin).


That's really it. I don't think electronics gets any easier than this.

The standard Arduino's analog input pins can read zero to 5 volts. If 5 volts is our maximum signal at 20 milliamps, that requires a resistance of 250 ohms:


R = V/I

R = 5 V/ 0.02 A = 250 ohms

If this were instead a 3.3V microcontroller, we'd require a 165 ohm resistor to read the full range output by the same math. Whichever reference voltage, you can use a lower resistor, but it cuts down the readable span.

We can now convert the measured voltage back to whatever units our signal is in. To do this, we just need a little algebra! We can plot an x-y chart, where the x-axis is the measured current/voltage/AnalogRead output and the y-axis is the process variable (pressure in this case). 

I live my life by the principles of slope intercept form

Usually, a precision resistor is used for the reference resistor, with a low temperature coefficient (change in resistance with temperature), but for my purposes, an ordinary resistor suffices. I had a nominally 220 ohm resistor I measured as 217 ohms actual resistance, and a 33 ohm resistor that measured true, which combined in series gave 250 ohms. We don't need exactly the correct resistance, though - we can compensate in code. Here's everything breadboarded up - not much to it:


The transmitter worked like a champ, with the measured signal tracking the manual gauge I had connected to it as I varied the pressure.


One other nice feature of the 4-20 mA signal scheme is that the low end of the signal output is 4 milliamps, not zero. This makes it easy to detect errors, as happened on the above data logging run when I bumped the wire around 10,000 milliseconds in. The raw reading went to zero, when it should have bottomed out at about 200 if it were a real zero signal. This tells me that something is up with the wiring at this point, and the data can't be trusted. If I wrote a program to use this transmitter reading as an input, I would know to handle any zero signal readings as an error, not as a true data point.


Here's the code: 
float PressureReading;     
float ResistorValue = 250;  //reference resistor resistance
float Pmax = 100;           //Max of process variable range
float Pmin = 0;             //Min of process variable range
float Vref = 5;             //Reference voltage for AnalogRead


void setup() {
    Serial.begin(9600);
    Serial.println("Time, Raw reading, Corrected reading");
}

void loop() {
  Serial.print(millis());
  Serial.print(",");

  //Read the voltage across the reference resistor
  PressureReading = analogRead(A3);
  
  Serial.print(PressureReading);
  Serial.print(",");

  //Convert the voltage signal to a pressure reading
  PressureReading =(Pmax-Pmin)*Vref/(1023*ResistorValue*(0.02-0.004))*(PressureReading-1023*0.004*ResistorValue/Vref);

  Serial.println(PressureReading);
  
  delay(500);
  
}

Sunday, October 30, 2016

DIY Signal to Pressure Transducer

I was bored, so I made a home-built signal to pressure transducer. You can use this sort of thing to control the position of a pneumatically actuated valve, among other sundry uses. It works by balancing the flow of air in to a chamber through a needle valve with flow of air out of the chamber through a solenoid valve. The solenoid valve can be quickly opened and closed. By adjusting the relative amount of time the solenoid valve spends open and closed, the pressure in the chamber can be precisely controlled.




The maximum rate at which air can leave the chamber must be balanced with the maximum rate that air can enter the chamber so the output can be varied over a wide range. The maximum exit rate is dictated by the size of the hole the air can flow through when the solenoid valve is wide open. I used a Clippard EV-3-12 solenoid valve I had sitting around, which from the given air consumption rate (0.6 scfm at 100 psi supply pressure), has a roughly 0.025" flow path. I wanted a slightly lower air consumption rate, so I made my own 1/64" (0.016") orifice fitting by filling a 10-32 fitting with epoxy and drilling a 1/64" hole in the set epoxy.

Nothing to sneeze at - you'll lose the drill bit!
1/64" hole? How in the world do you do that? With a 1/64" drill bit of course! I got a couple of these TINY bits for just this sort of occasion. A handy dandy orifice flow calculation shows that this should have a 0.25 scfm air consumption when choked from 100 psig,

The air inlet area must be even smaller than this if it will allow pressures to be controlled over a wide range. Luckily a needle valve I have can be slightly cracked open to just allow enough flow that allows a good range output with decent (5-10 second) re-pressurization times.

The solenoid valve takes 12 volts to open. An IRF510 transistor connected to an Arduino's digital output pin allows the amount of time the solenoid valve spends open and closed to be adjusted to change the equilibrium pressure in the chamber. You can't just use the Arduino PWM output to throttle the valve, though - the on/off frequency used by the PWM pins is way, way faster than the amount of time the valve takes to open and close (which is 5-10 milliseconds from the valve specs). When the output signal to the valve is greater than 50%, I programmed the valve to spend 20 milliseconds off, followed by a variable amount of time on proportional to the output signal. Vice versa for when the output is less than 50%.

I then connected the pressure chamber to the pneumatic actuator of a ball valve I had sitting around.  Although flow control with a ball valve is usually a pretty dicey affair (not that I haven't seen it done), this ball valve should now be able to somewhat precisely control flow! I see another day of boredom avoided with that!

Here's the whole shebang in action:




Sunday, August 21, 2016

Cheap pressure transmitter hack attempt...and failure

Looking for a low cost pressure transducer, I came across these mini digital tire pressure gauges. I thought there might be some signal on its circuit board I could extract to read the pressure from another device. Let's crack it open and see!

The gauge is a Slime brand, model 20268

First things, the device comes with a Schrader valve type fitting to connect to a tire stem to read the pressure. I wanted to connect it to an NPT fitting, so I filled the Schraeder valve connection  point with epoxy. Once it set, I drilled and tapped a 10-32 hole, for which I had adapters to NPT fittings.




On the inside, the device has a pressure sensor chip directly on its main circuit board, which is exposed to the pressure tap. An o-ring seals the circuit board to the pressure tap in a half-torso'd attempt to keep leaks to a minimum. Interesting.

Under the cover


Other side of the circuit board. Note the pressure sensor chip with the O-ring around it. Not the tightest seal, but I guess it really doesn't need to be for measuring a tire's pressure.

Back side of the plastic case - the o-ring fits in the circular groove at the top.
Putting the gauge back together and applying air pressure, it read right in line with my air compressor's gauge. It does appear to latch the highest reading it observed, keeping that reading even after the pressure was removed. This makes sense for a tire pressure sensor - you may not be in a position to easily read the gauge when pressing it against a tire valve stem, but it will retain the reading after you remove it from pressure.

See the force over area!
 
The foolproof way to read a pressure off of the board would be to read the LCD signal points. I really didn't want to eat up 12ish digital inputs and then code an interpreter that converted the LCD signal to a number, so I continued trying to find some sort of output signal on the board.

There are several test points on the circuit board, but I couldn't discern any useful signal from any of them that seemed to vary with the applied pressure. Striking out on them, I attempted to go straight for the sensor chip. I soldered wires directly to the "S+" and "S-" test points, which I took to be the sensor output. Hooking these up to an Arduino's analog input points, I couldn't see any discernible signal when I varied the pressure - they gave a ~1V output for 200 milliseconds, followed by 1 second at 0V, repeated, regardless of the applied pressure. 

Putting the gauge back together, the gauge no longer works - only reads zero now, regardless of applied pressure. I suppose I probably fried something when soldering on to the test points, or inadvertently applied a voltage somewhere that fried the sensor, so this one is a strikeout. There are several other cheap tire pressure gauge models out there, so I may try again with another.

Hey, $7 for a weekend of tinkering ain't a bad deal.


Saturday, July 23, 2016

Arduino-Cryocooler Handshake!

Just look at this!

The curved traces are "artistic" or something
That's my first attempt at having a printed circuit board manufactured, and it turned out mostly okay! I had breadboarded-up an Arduino-cryocooler interface circuit, and was dreading wiring it up using perfboard. I'd heard of the numerous small-quantity PCB manufacturers around these days and decided to try one out, Seeed Studio. I drafted up the circuit in Fritzing, a free PCB CAD program, uploaded the Gerber file output to the Seeed Studio website, and ordered 5 (the minimum quantity) boards for $19. Three to six weeks later, the boards showed up, apparently after a wild weekend in Singapore, looking just like I'd drafted! I soldered one up, powered it up...and realized I'd omitted one trace wire and one resistor.
Whoopsie! Good thing I'm a very forgiving customer to myself.
A couple Whoopsie Wires later and it was transmitting an external thermocouple reading to the cryocooler! It does this by simulating a resistance between two pins on the cryocooler's main control board. These pins are normally connected to the thermistor in the Superlink's Dewar. This thermistor's resistance varies between roughly 5 to 12 kiloohms in the normal working temperature range of the cryocooler. I made a circuit consisting of a 12K resistor in parallel with two optoisolators, one in series with a 12K resistor and one in series with an 800K resistor. Both optoisolators are controlled by an Arduino PWM pins, and open/close the path to give an effective resistance that corresponds to the proper temperature. A capacitor is installed across the positive and negative leads to smooth out the PWM pulses.


Two optoisolators are used because when I tried with just one, the Arduino's 8-bit PWM output wasn't fine enough to adequately control the output when the temperature was close to the lower end of the range. The second optoisolator is in series with a much higher value resistor, and thereby contributes a much smaller signal to the output. Playing around with the values, 800K was approximately the correct value to make the fine output roughly linear between the coarse pulses, giving it roughly 12 bits or so of usable PWM output range, which is fine enough for this purpose. I used optoisolators rather than transistors because I don't know what's going on in the thermistor measuring circuit - I didn't want to take any chances with frying anything on either side with weird voltages.

The Arduino (actually an Ardweeny arduino clone) also connects to the cryocooler's serial interface to read the temperature it just attempted to transmit to the cryocooler, correcting it if it's off. It also reads the power output to the cryocooler. I added a nice little OLED display to show the measured temperature, temperature reported by the cryocooler, and the cryocooler power, so it doesn't need to be hooked up to the computer to read these values. I also added an on/off switch to allow me to soft shut down the cryocooler through its software before turning off its power. This should help avoid damage from hard stops.

The OLED in Alluring Aqua
I now have a self-contained, mobile liquid air generating machine! First order of business is to (of course...) make liquid nitrogen ice cream! I can't wait to see how the most expensive bowl of ice cream I've ever had tastes! After that, it's back to the drawing board to work up a way to liquefy gases other than air.



Update: Aw hell ya

I've loaded the board design (with corrections to my original errors) and the Arduino code here.

The other parts of the quixotic Cryocooler quest are here - Part 1 and Part 2 and Part 3 and Part 4

Saturday, March 19, 2016

Simplified Superlink Interface!

Here is part 4 of the Cryocooler Saga! You can see Part 1 and Part 2 and Part 3 also.

tl;dr - Here's a program for interfacing with a Superconductor Technologies Superlink

There's a lot of data pumped out by the cryocooler while it's operating, including various temperatures, voltages, power consumption, et cetera. Unfortunately, I could only access that data through the manufacturer's software, which won't run on anything beyond Windows XP. I have a 10 year old laptop that will run it, but I mean c'mon, it's a ten year old computer. I'm not sure how much longer ol' Speed Turtle here is going to keep on staying critical-failure-free.

High Technology
Besides, I'd ultimately like a way to replace the cold-side temperature measurement the cryocooler uses with a different device, which would be greatly simplified if the device measuring the temperature can see what it's transmitting to the Superlink.

The System Status Portal software turns out to be a pretty face for the serial back-and-forth between the computer and the Superlink. The link runs at 19200 baud, 8 data bits, zero parity, no flow control. I ran a serial monitor program while the computer had the software open and talking to the Superlink, and it showed that the back and forth looked something like this:

Request: 3/13/2016 9:59:32 PM.57264 (+0.2567 seconds)

 3C 53 59 20 4F 50 3D 22 4F 4B 22 2F 3E 0D 0A      <SY OP="OK"/>.. 

Answer: 3/13/2016 9:59:32 PM.57264 (+0.0000 seconds)

 3C 53 59 20 4F 50 3D 22 4F 4B 22 2F 3E 0A         <SY OP="OK"/>.  

Request: 3/13/2016 9:59:32 PM.60364 (+0.0000 seconds)

 3C 54 4D 20 4F 50 3D 22 47 54 22 20 4C 43 3D 22   <TM OP="GT" LC="
 43 52 22 2F 3E 0D 0A                              CR"/>..         

Answer: 3/13/2016 9:59:32 PM.60364 (+0.0000 seconds)

 0D 3C 54 4D 20 4F 50 3D 22 47 54 22 20 4C 43 3D   .<TM OP="GT" LC=
 22 43 52 22 3E 30 20 30 20 31 38 20 33 35 3C 2F   "CR">0 0 18 35</
 54 4D 3E 0A                                       TM>.            

Request: 3/13/2016 9:59:32 PM.63364 (+0.0000 seconds)

 3C 54 4D 20 4F 50 3D 22 47 54 22 20 4C 43 3D 22   <TM OP="GT" LC="
 41 43 22 2F 3E 0D 0A                              AC"/>..         

Answer: 3/13/2016 9:59:32 PM.63364 (+0.0000 seconds)

 0D 3C 54 4D 20 4F 50 3D 22 47 54 22 20 4C 43 3D   .<TM OP="GT" LC=
 22 41 43 22 3E 41 43 42 20 33 20 41 43 39 20 31   "AC">ACB 3 AC9 1
 30 3C 2F 54 4D 3E 0A 0D                           0</TM>..    

The interaction consists of query strings sent by the computer that are returned with the data requested. Pouring through the decompiled code for the System Status Portal (what can I say, I live a wild life), I managed to figure out which query strings returned the data I was interested in. Turns out, if you want to find the cold side temperature and cooler rejection temperature, you ask:

<TP OP="GT" LC="MS"/>

which is responded to with something like:

<TP OP="GT" LC="MS">F 6D80 3BE8 4D60 3C78</TP>

Each of those five hex numbers in the middle there correspond to five different measurements it's returning. Turns out the cold side wide range temperature is the second one (6D80) and the cooler rejection temperature is the third one (3BE8). That hex number is pretty meaningless, though. Pouring through more of the System Status Portal code, I found the formulas it used to convert those numbers to actual temperatures. The formula is:

Temp = (5 * (hex string converted to decimal)/32768 - Offset)/Gain

where for the cold wide range temperature, the offset is 5.814 and the gain is -0.01559. There's a different offset and gain for the rejection temperature and the other temperatures returned. Convert the two-letter parts of the query string ("TP", "OP", "LC", "MS") to their ASCII equivalent hex codes (TP=5450) and then convert that to a decimal number (hex 5450 = 21584), and search the System Status Portal code for that decimal number to work through the logic to find which data points are revealed by which query strings!

Similarly, the cooler power draw can be elucidated with the proper query string and formula, as can every other measurement that shows up in the System Status Portal. In addition to reading measurement values, the System Status Portal can also change the operating state of the cooler, switching it between manual mode where the cooler can be shut off and automatic mode, where the cooler will automatically ramp up power as the cold side temperature declines, keeping the cooler within its safe operating limits. This is accomplished with another query string,

<TP OP="ST" LC="SM">1 4</TP>

will set the cooler to manual shutdown mode, while

<TP OP="ST" LC="SM">0 4</TP>

will turn it back to automatic mode.

I needed an excuse to brush off my infantile Python skills, so I wrote a user interface that will allow you to see the cold side wide range temperature, cooler rejection temperature, cooler power, and status. You can also toggle between Manual Shutdown mode and Automatic mode, so you can shut down the cryocooler safely without the System Status Portal program. I've loaded the Python code to github - you'll need Python installed (I used version 3.5), along with the Tkinter and pySerial libraries to run it. I've only tested it on my Windows 10 computer, but it appears to work pretty well. Here it is on Github. There's a lot of room for improvement and expansion, so if you want to add functionality, go for it!




I next plan to replace the cold side temperature measurement with an external thermocouple, using an Arduino to simulate a resistance to send the temperature measurement to the Superlink. I'll then use the serial handshake to allow the Arduino to talk to the Superlink to read the temperature it's trying to simulate, allowing it to precisely control its output to make sure the Superlink is seeing the same temperature it is.

Friday, February 12, 2016

A goofy 1000 psi air compresor...using a pressure washer

Hey, not all projects have to be practical, right? Sometimes, you just start putting things together and end up with something like this:


For reasons that ultimately led to my cryocooler purchase, I wanted to have a source of quite high pressure (~1000 psi) air. Most ordinary utility air compressors top out at about 150 psi, which, working in the oil and gas industry, seems like small potatoes. I wanted some pressure, I'm talking ANSI 600 class at least. In my line of work, we use devices called blowcases to pump liquids using high pressure gas. They're convenient when you need to pump a liquid to relatively high pressures and don't have any utility electric power, but do have a source of high pressure gas. I figured I could do this in reverse, taking a source of high pressure liquid to pressurize a gas.




The "compressor" works by allowing gas from a lower pressure source (a shop air compressor capable of 150 psi discharge pressure) to enter the compression chamber. Water is then pumped in from the bottom, compressing the gas and allowing it to flow into a reservoir. Once the water reaches a high-level sensing line, the flow of water in is stopped and the water is drained out the bottom. The cycle is then repeated until the pressure in the reservoir is the desired pressure. The level is sensed by a magnet wire inserted into the chamber through a hole drilled in a plug, and then epoxied in place. An Arduino was used to sense when the resistance between the chamber walls and the sensing wire fell, indicating that the water level had reached the wire (good thing mildly impure water is a good conductor). The Arduino then switches a pair of automated valves via a solenoid valve to shut off flow from the pressure washer and drain the chamber. After a set time, the valves are switched again and the cycle repeats. Here's a terribly shaky video explanation of the contraption. Yes, that (was) my kitchen. No, that floor no longer haunts my dreams. Never buy a house, but that's another anthology.



A nice thing about living in an oil field (there are a small handful) is that the local plumbing supply store sells Schedule 80 A106 Grade B pipe capable of withstanding well over 1000 psi and 3000 psi rated fittings. I bought some 2" pipe nipples, and couplings, bushings, and tees. From McMaster Carr (truly the greatest retailer in the solar system), I bought some 1/4" NPT fittings and steel tubing. Off of ebay, I found some reasonably priced 1000 and 2000 psi rated ball valves equipped with pneumatic actuators and an Asco solenoid valve. One happened to be installed as fail open and the other as fail closed, which made it possible to control both valves with the single solenoid valve (although it's pretty easy to switch the fail position on pneumatic actuators of this type). Hooking the pressure washer up to the 2000 psi actuated valve and using the 1000 psi valve to drain the chamber, the contraption actually worked to get up to beyond 900 psi!

pics or it didn't happen

Granted, it did turn out to be quite a pain in the butt to set up, and the time to pressurize the air was quite long, so why in the world of alabaster did I want to do this? At the time, I was thinking the easiest way I could generate liquid air was to allow high pressure air to go through a Joule Thompson expansion to cool it down to liquefying temperatures. However, to JT straight to a liquid, you need to get on top of the liquid envelope on the pressure-enthalpy diagram, that is to say pressurize it beyond its critical pressure, which for air is about 37 atmospheres or 550 psi. After that, you still need to chill it down to about 150K and then JT it to get it into the liquid envelope, but I figured 150K would be easier to achieve than 80K. Turns out, not really, I never got a way to get to those temperatures until I got my cryocooler, which could get all the way to 80 K anyways. It was a fun proof of concept nonetheless.

Thursday, January 7, 2016

Superlink teardown

Here is part 3 of the Cryocooler Saga! You can see Part 1 and Part 2 also.


So what does all that stuff in the box do? What's necessary to keep it running happily along and what can be cut out? Let's figure it out!

First off, what do we have under the hood? Here's a rough labeling of some of the important parts:

Click for big!
Wow, that's crammed in there. Nice!

In addition to the cryocooler that's the reason I bought this whole shebang, there's a power and control circuit board, a dewar containing the superconducting elements (connected to the cryocooler with a vacuum flange, presumably to maintain a tight seal on the cold side to minimize leakage), and a cooling fan that forces air through the cooling fins on the heat-rejection location on the cryocooler. There's also a jumble of RF wires that presumably connect to whatever it's supposed to be super-filtering. Those can be disconnected from the dewar by loosening each of the screw connections.

The cryocooler is held in position with two machine screws near the cooling fan, and the dewar is held in place with a pipe clamp. The cryocooler screws can be easily accessed by removing the cooling fan first, as shown below. First, I removed the dust filter in front of the fan. This makes visible the four screws holding the fan in place.





Once the fan is removed, the screws can be removed by putting an allen wrench (or a star drive, as I used) through the fan hole.



Next, I disconnected the back plate with all of the RF wires from the base of the unit by removing a few screws.

The two on the bare steel tab. Ditto on the other side.

Next, I disconnected the clamp holding together the vacuum flange connecting the cryocooler and the dewar near the heat rejection fins, and completely loosened the pipe clamp holding the dewar down.



This allowed me to remove the entire cryocooler-Dewar assembly, or more easily, separate the two and take them out separately. The cryocooler's cold head is covered in a thermal paste.



The dewar looks to be of an interesting construction - it has a piece that slides up the cold head past the flange, which appears to be welded on the end. My guess is that it's two pipes with a small gap between them in which there's a vacuum that further insulates the cold head from the heat rejection area. Maybe someone who knows better can correct me.





Before removing the cryocooler, you'll need to disconnect a few wires from the circuit board. Here's an annotated photo of what's going on there. I disconnected the rejection temperature sensor (bottom right) and the cryocooler power connector (bottom left) and loosened the cable ties holding the wires in place in order to remove the cryocooler. I also needed to disconnect the wire bundle to the dewar on the right in order to remove it.

Click for legible
:

As mentioned in the photo and a previous post, the only signals needed to run the cooler are the rejection temperature sensor and the cold-side temperature sensor from the dewar (which is the pin pair the fourth from the bottom on the wire harness). Some of the other pin pairs show a voltage difference while the board is running, but I can't figure out what they're doing, and it doesn't seem to throw any faults if they're disconnected.

Me trying to figure out what the pins do. Turns out, not much that I need worry about, maybe?

Next up: Spoofing that temperature signal so I can use my own cold side temperature sensor!