Michael75:
I've bumped into this circuit problem a couple times in different projects. I want to create a constant current source (1-3 amps) that I can control from an Arduino. So I would write in code, output say 1.2 amps constant current, or output 2.4 amps. A value I can have change at runtime in the code.
Currently I have been having the arduino just turn on or off a 1 amp constant current source with a relay [...]
(Note, the 1-3-2 pin numbering in the illustrated circuit doesn't agree with the 1-2-3 numbering I've seen in regulator spec sheets.)
In constant current circuits like that illustrated, load current flows from the output pin through R1. The regulator senses the voltage dropped across R1 and raises or lowers output voltage so the drop is equal to V_ref, which is (in effect) 12 V for an LM7812 and is 1.25 V for an LM317, as Peter_n mentioned. With a 35 V max input voltage, the LM7812 also has less headroom anyway than the LM317 with a 40 V limit.
Using 1.25 V instead of 12 V across R1 produces only 10% as much heat in R1, and also reduces the input voltage that you need to supply by 10.75 V. As a concrete example, for 3 A output current, if R1 drops 12 V it's a 4 Ω, 36 W resistor. If R1 drops 1.25 V it's a 0.42 Ω, 4 W resistor.
For higher currents than the LM317's 1.5 A max, you might look at 3 A and 5 A regulators at Digikey and other suppliers. Eg, AZ1084CD-ADJTRG1 at Digikey.com is a 5 A regulator, 56¢ in singles. Note, its input voltage is limited to 12 V.
You could vary the output current several ways. You could use several relays and have several different resistor sizes to combine in parallel to make up R1.
Or, if you don't mind some experimentation and your app has no life-safety issues, it might be possible to put a current-sensing resistor (eg 0.1 Ω) on the ground side of your load, attach a PWM output to a low-pass filter (LPF) connected to the regulator's sense input, and use a feedback loop to get desired current output. The loop would read the current-sensing resistor's analog voltage; if it's too low, increase PWM setting, etc. This approach can work if your load is stable and resistive, and if setpoints change slowly. For faster-changing setpoints, DAC output rather than PWM+LPF would be needed. For dynamic loads, DAC output plus some control theory would be needed if instability is to be avoided.
Note, the PWM output might need to drive a voltage shifter (a transistor and resistor) so that voltage at the output of the LPF could exceed the 3.3 V or 5 V available at Arduino pins.