Hardware (EAGLE PCB), firmware (Arduino C++), and software (LabView VIs) for the annealing controller I am building for the Spinquest experiment, E1039, at Fermilab in Batavia, Illinois.
The system regulates the temperature of an NH3(s) polarized spin target to ~75K (roughly N2(l) temperatures) to replenish the paramagnetic centers, which catalyze dynamic nuclear polarization (these paramagnetic centers are lost over the course of the proton bombardment).
Two T-type thermocouples and two MOSFET-driven resistive heaters at either end of the target holder are used to maintain a constant temperature as well as a constant temperature gradient in the axis transverse to the incident proton beam.
From a LabView VI interfacing to the Arduino's serial port, the temperature setpoint can be changed or the heaters can be shut off entirely. The VI also allows real-time monitoring of the temperatures in the system and the status of the heater fuses (VI not built yet).
Serial port speed: 250kbit/s
Heater power: up to 120W per channel (24V max, 5A max), for a total of up to 240W thermal power output
Power supply requirements:
- A/C inlet: 120VAC, 60Hz at 2.5A with both heaters at maximum power. A fuse will blow if the AC/DC converter draws more than 2.5A.
- Arduino USB port: 5V at 500mA
- Manual box DC jack: 9V at 100mA, center-positive
Hardware is divided between two boxes: the annealing control box, which does most of the work, and a manual control box to operate the switches remotely in case of the microcontroller failing.
AnnealingController is the main unit: an Arduino UNO-compatible shield that switches two MOSFETs to control the heating elements. The heater circuit includes fuses and fault checking on each heater. This board also has transistor drivers for the front-panel LEDs, a connector for an I2C LCD and input keys, and the ThermocoupleAmp board.
ThermocoupleAmp R2 has an ADS1120, a dual differential ADC with internal amplifier and SPI interface. Each thermocouple is biased to 2.5V (mid-supply) with megaohm resistors - do not try to ground the thermocouple leads. Each thermocouple input has a differential single-order low-pass breaking at 1.6kHz and two common-mode single-order low-passes breaking at 16kHz. The filters also provide some isolation protection in the form of a 1k series resistance. Together with the decent input protection of the ADS1120 (tolerant of 4kV static, DC exceeding rails by 0.3V), we should be good as long as you don't short the thermocouple to AC or something like that. The connectors are designed for T-type thermocouples. I use the internal temperature sensor of the ADC to do cold-junction compensation.
The old ThermocoupleAmp R1 used MAX31855T amplifier/digitizer ICs. The MAX31855T is f***** cursed - avoid it.
ManualController has dual 555-based adjustable duty pulse generators with a period on the order of one second. The power supply is a 9V wall jack. To get the system to work properly, I had to ditch the 5V regulator and run the 555s on 9V. The RUN SW pads were shorted since the RESET no longer went low enough, and I just used the RUN switch to turn the power supply on and off.
There are four fuses in the device that can blow: a 2.5A 120V glass fuse on the rear panel, a 15A ATC fuse inline with SUPPLY+ inside the box, and two 7.5A ATC fuses within holders on the main board.
The most likely components to fail are the ThermocoupleAmp R2 board and the two MOSFETs on the shield that switch the heaters. Contact me (rhn9bta@virginia.edu) if you need a new ThermocoupleAmp board soldered up. The MOSFETs are easily replaced: snip the leads above the board, desolder the pads to clear the holes, then solder in a new one. The ones on the board right now are IRLB8721's. Any logic-level (gate threshold < 2V) N-channel MOSFET with maximum drain-source voltage well above 24V (or well above whatever you are using for the power supply) and maximum drain current well above 5A will do, really.
An emergency stop switch (RUN/E-STOP) on the box cuts power to the heaters manually. The board registers the emergency stop as though both heaters' fuses had blown. This is for the worst-case scenario where the heaters need to be shut off to avoid boiling all the liquid helium, but a software failure prevents it.
The MANUAL/CPU switch serves to disconnect the microcontroller system entirely and allow the heaters to be switched from a control box in the operator's room. In case of total software and hardware failure, the annealing system will still be able to vary the heat output for each heater individually. In MANUAL mode, the microcontroller tri-states the heater switch signals so that incoming signals from the manual control box can override.
NOTE: Do NOT switch on the manual control box while the microcontroller in the annealing box is unpowered (the USB cable must be connected to a host device or power adaptor). If you do this, supposing the heater power supply is on, the box's input protection circuit will malfunction and the MOSFETs will receive a switch-on signal just above their 2V threshhold. Operating in the triode region, they'll desolder themselves in seconds and you'll have to find a new set. It's perfectly safe to leave the manual control box connected to the system, and even running, whether the box is in MANUAL or CPU mode.
There are four LEDs on the front panel:
- COMM (blue): flashes upon receiving a valid packet over the serial port
- ERR (red): flashes slowly for a non-critical error (simple loss of serial control, for example), or flashes quickly in case of a critical error with the temperature sensors or heater fuses that could hinder operation. Blinks periodically in MANUAL mode.
- HT A (green): lit while heater A is switched on. During annealing, it should flash with a variable duty cycle as the controller attempts to regulate the temperature. The light continues to work in manual mode - it's a good way to test the wiring to the manual control box without the heater power supply switched on.
- HT B (green): ditto heater B
The wiring from the heaters should be connected to the appropriate screw terminals on the terminal strip using spade connectors, after passing through the strain relief entry in the rear of the box. Polarity does not matter as far as I know (I do not know the specs of the heaters).
The thermocouple wires should pass through their strain relief entry, then mate with the connectors on the ThermocoupleAmp board: use only T-type thermocouple terminations, or the readings will not be reliable even to within a few Kelvin. Ensure the polarity is correct. Do not ground or otherwise allow electrical contact between the thermocouple and the experimental apparatus; use conductive insulating epoxy. Do not use extension (copper-copper) wires; this will prevent us from using the ADC internal temperature to do cold-junction compensation. Just run T-type cable all the way to the box.
Look over the wiring diagram (TODO) to make sure all is well.
Install 5A ATC-size automotive blade fuses in the fuse holders on the shield, and a 10A fuse inline with the heater power supply. Install a 2A AC fuse in the fuse holder near the IEC power entry. Plug in an IEC cord to bring the power supply online, and adjust the knob to 12VDC for initial tests at low heater current. The voltage can be raised to 24V once the system is checked out. The heaters will remain off so long as the Arduino does not get USB power from the Ethernet-serial port converter.
Put the heater control switch to the CPU position. Put the system into emergency stop (front-panel switch) so that the heaters will not switch on, then power up the Arduino and upload the latest firmware. Test LabView communication (look for blinking COMM LED on message reception from LabView) and that the system controls the heaters as expected (watch LEDs HTA and HTB).
Flip the emergency stop switch to RUN and see if the temperature regulation works. If more thermal power is required, the power supply voltage may be increased by turning its orange knob, but beware that the MOSFETs break down at 30V!
The wiring from the manual control box consists of three conductors: HTA, HTB, and GND. HTA and HTB go to the supply voltage of the manual box (~9V) to switch the FETs in the annealing box on, or to ground to switch it off. Pass these wires through the strain relief on the back of the annealing box and connect them to the terminal strip.
Power the manual box from the 9VDC output AC adaptor through the jack. Check that the RUN/STOP switch and knobs for each channel work by watching the LEDs on the manual box blink.
To test the system, power up the annealing box with the AC cord (does not matter if the Arduino is powered via USB). Switch the emergency stop to RUN and the heater control to MANUAL to use the signals from the manual box. The front-panel LEDs for the heaters will not light in this mode; you will have to verify the heater currents are being switched with a meter.
In case one of the little wires breaks off or something, here's a key to help put it all back together. The lines from the Arduino run as a few different bundles of ribbon cable:
Power (green screw terminals)
| Arduino Pin | Color | Destination Pin |
|---|---|---|
| SUP+ | red | Power supply V+ |
| RET- | black | Power supply V- |
| HTA+ | red | terminal strip position 5 |
| HTA- | black | terminal strip position 6 |
| HTB+ | red | terminal strip position 7 |
| HTB- | black | terminal strip position 8 |
| SIG GND (either) | black | Power supply V- |
Front-panel interface LED board (lines go to a five-pin connector on the shield)
| Arduino Pin | Color | Destination Pin |
|---|---|---|
| 5V (OC) | yellow | LED anodes on LED board |
| HTB | orange | Second green LED cathode |
| HTA | red | First green LED cathode |
| ERR | brown | Red LED cathode |
| COMM | black | Blue LED cathode |
Front-panel CPU/MANUAL switch
| Arduino Pin | Color | Destination Pin |
|---|---|---|
| D9 | white | CPU/MANUAL switch common terminal |
| GND near D13 | black | CPU/MANUAL switch MANUAL terminal |
Thermocouple amplifier (lines go to an 8-pin connector on the thermocouple amp board)
| Arduino Pin | Color | Destination Pin |
|---|---|---|
| D13 | green | TC Amp SCK |
| D12 | blue | MOSI/DRDY |
| D11 | purple | MISO |
| 5V (TC amp power header) | red | 5V |
| GND (TC amp power header) | orange | GND |
| GND (TC amp power header) | yellow | GND |
Manual input protection board
| Arduino Pin | Color | Destination Pin |
|---|---|---|
| 5V | red | 5V |
| GND | brown | GND |
| D6 | orange | heater B signal |
| D5 | yellow | heater A signal |
The rest of the wiring is pretty straightforward: the AC inlet has the fuse holder in series with the hot line (black), then all three AC lines run to the power supply terminals. Two ground lines run from the V- terminals on the power supply to the shield. One red line runs from the V+ terminal through the RUN/E-STOP switch and inline fuse holder to the shield.
The Arduino firmware consists of C++ classes to read the thermocouples, run PID calculations (modified AutoPID library), control the heaters, blink the front-panel LEDs, and communicate over the Serial port. The main.cpp file ties it all together. You can work on the firmware most easily using VSCode with the PlatformIO extension and the Arduino framework installed.
The system expects the following commands - everything else is ignored completely. In the event that no valid commands are received for 10s, the heaters are shut off (emergency stop).
<SET,-32.5>changes the temperature setpoint for both heaters<OFF>causes an emergency stop (heaters off)<PID,6.9,6.9,42.0>sets the P, I, and D gains for both control loops<SAV>burns the PID parameters to non-volatile memory - they will be the gains used after a power cycle. Send this infrequently to avoid wearing the EEPROM. Also, running the command blocks the Arduino ~50ms...<RST>causes a software (watchdog timer) reset of the Arduino MCU
At 1Hz, the system transmits a status data packet:
<DAT,uptime (s), setpoint (degC), A temp (degC), B temp (degC), ADC internal temp (degC), heater A duty cycle (%), B duty (%), Kp, Ki, Kd>
If there is an error, heater operation will stop and an error packet will be sent, also at 1Hz:
<ERR, ADC errcode, fuses blown (A|B)>
The ADC error code is constructed using bitfields OR'd together. Bit 0 indicates an SPI bus problem - check the wiring to the TC amp board. Bit 1 indicates a bad internal temp. reading (outside of 3-35degC). Bits 2 and 3 indicate bad readings from the thermocouples - check the thermocouple wiring. The ADC inputs may also have been damaged. When the problem is resolved, the bits clear automatically - except for bit 0, which requires a reboot.
It ain't started yet.