What is Freeside?

Freeside is a Georgia nonprofit corporation, organized to develop a community of coders, makers, artists, and researchers in order to promote collaboration and community outreach. Learn more »

Offroad Wheelchair Update 1 - To Retrofit or Reinvent?

Recently, we at Freeside Atlanta teamed up with the Alchemical Arts Alliance and My Inventor Club to design and build an Offroad Wheelchair so that our friend Robin can get around their events. Together, we've raised about $2,000 for the project.

The design phase is usually the most difficult part of the projects, and it is often the most expensive place to make a mistake. Committing the resources to a poorly-designed project can cause the entire thing to be wasted, so we designed the Offroad Wheelchair project very carefully.

We started with the constraints – We need ease of maneuverability, an ability to overcome obstacles and take fairly steep inclines, longevity to make it through events up to a week long, and recoverability in case it gets stuck. Also, biggest two constraints – Budget (~$2000) and time to prototype (2 months)

From that, we landed on 3 design options –
1 – Electric motors with onboard generator for periodic battery charge
2 – Modifying an existing lawnmower or outdoor vehicle with hydraulic controls and automation
3 – Modifying a zero-turn lawnmower to suit our purpose

After weighing the options, we chose option one for its low noise and high efficiency. Next step - simulate the design. I used the website Study Physics to figure out the torque requirement to pull a simulated wheelchair + passenger up a given slope. Then I simulated it in a spreadsheet starting with the worst-case scenario so I could play with the numbers. The inputs are in orange and the rest are calculations.

In other words, the force required to take a vehicle up a 15 degree slope is a bit more than half of the force required to lift it all the way off the ground. To find the torque requirement, the force needs to be distributed around the wheel, since the wheel radius affects the leverage exerted by the motor.

Therefore, the minimum torque of the motors is about 200 pound feet. Is that feasible for an electric motor? Let’s look at the best motor example I could find - 

This means that the system required two very powerful electric motors, running near peak torque continuously, and geared down 60x. They exist, but they are about $600 each and don’t usually match each other’s output exactly. Plus, the motor controllers are $200-$400 each! That means that this project is neither feasible nor practical, as the entire budget could be spent on 2 motors with their respective transmissions and controllers. It won’t work. But, this is why we simulate. It’s time to drop back and try again.

The hydraulic modification of an existing vehicle seems interesting, but also time-consuming. Plus, it wouldn’t be able to pivot in place like the other two design options, which is important to delivering the rider to exactly their target. Not to mention that the drive of the wheels will probably be locked together, so there is nothing stopping the thing from sliding down a slope. It also requires the modification of a ~$1000 platform with up to $800 in hydraulics and most options aren’t configured for somebody to easily get into from a wheelchair.

Then, Shane from My Inventor Club sent me an email about a zero-turn mower that was available in our price range. Zero-turn mowers use hydrostatic transmissions to convert the high-rpm, low-torque energy from an engine into low-speed, high-torque power with hydraulics. The mower we chose is a Grasshopper 725k. The actual torque isn’t listed in any of the data sheets, but the horsepower (25) and wheel diameter (22in) are. So now we just need to find the torque and update our simulation to see if it will work.
If we know how to find torque then we just need to find the rpm at the wheels at the top speed, discount it by about 30% for conversion losses, and that will be near our actual torque.
First, get the top speed to feet per minute – 

Then, turn that to rpm using (the diameter of the tire) * (pi) to get the ground it covers per revolution.

Finally, you can do the torque conversion – 
 The zero-turn mower is 800lbs, so it is much heavier. The torque required to haul it up a 15 degree slope is 530 pound-feet, so it might be able to crawl along if it can keep traction. However, rolling over would be a concern at that angle anyway. Therefore, the zero-turn is feasible and reasonably meets the requirements of the project.

We can look into supplementing the power of the motors with a winch if the vehicle gets stuck somewhere that the torque/traction can’t overcome and reduce engine noise, but we're in the ballpark now. So, we’ve settled on a design – a retrofit of a zero-turn mower with a winch. It will be faster and more cost-effective to retrofit a used device that has been engineered to a similar task than to design and build something new from scratch. However, this platform could serve as a prototype for some future design, so we can work out the issues through iterative prototyping.

Until then, we’ll do the most effective and cost-effective Offroad Wheelchair that our constraints allow and document it so others can duplicate and improve the idea.

Check in on the Offroad Wheelchair page for links and info, including the simulation spreadsheet that I used (you get to point out my mistakes!) and the first video of the mower that we selected.

Precision Low Current Measurement w / Feedback Ammeter


If you've been following along on my journey to learn electronics design, you'll know I've been working on a motorcycle power supply. It's getting pretty close to finished and its time to do testing. The last series of blogs were about a constant current load testing device. I needed that to test the power supply under different load conditions. This installment is about the opposite end of that spectrum, what happens when the circuit is "off". Because lots of motorcycles tend to be parked for months without being ridden I need to verify that my device does not contribute to early battery failure. To do that I need to measure the current consumed when it is plugged in but off. We are talking about very small currents though so very high precision measurements are required.


Normally, you can use a digital multimeter for this purpose but for measuring small currents this not as straightforward as it seems. Ammeters are connected in series with a circuit and while a perfect ammeter would neither add or subtract anything to the circuit, it would just observe, in the real world ammeters are not perfect. Standard multimeters use a current shunt, or a resistor in series, and measure the voltage drop across that resistor. These designs unfortunately introduce something called burden voltage. This is the voltage dropped across the resistor used for measurement. This can be kept at a minimum by using small resistors but it cannot be avoided with a shunt ammeter. When you try to measure small currents with a DMM you can sometimes get grossly under reported currents caused by the burden voltage of the measurement circuit. 1

An alternate method is to use a feedback ammeter which measures the voltage dropped across the shunt and adds that much voltage back into the circuit. This sounds fancy but in fact is not that complicated once explained. That is my intention today.

Feedback Ammeter
The basic schematic above is the text book model of a feedback ammeter. A current goes into the inverting input (the current is represented here as a voltage in series with a resister which is the text book definition of a current) of an op amp and a voltage whose size is proportional to the input current comes out of the op amp's output as Vout. The burden voltage in this circuit would be the voltage difference between the inverting and non-inverting op amp inputs. Because of how op amps work though, this is almost zero.

This schematic makes it look so easy and I despite my best efforts to build it true to this diagram I failed to find success. The secret sauce is how you power the op amp. In order for me to make it work, I needed a floating power supply and I needed it referenced such that half of the floating power supply's potential was above GND and half was below GND. The wikipedia page 2 offered the tidbit about the floating power supply. With that I was able to get a voltage measurement that was proportional to the current input but there was a DC offset that changed with the voltage applied to the op amps. Dave Jones' uCurrent device's schematic 3 offered the final missing piece which was the referencing the power supply to half the potential. Once I got that figure the circuit was a winner!

Useful resources:
www.keithley.com/data?asset=6169
http://www.ni.com/white-paper/5448/en


My schematic
Circuit on breadboad





Constant Current Dummy Load - Complete


The project is finished. The units have been built and sent off for use. Much was learned. Here are some insights.
First, don't design a PCB for the lowest cost. That just increases your costs later. I made the the board narrower than was convenient to save $20 and I ended up wanting to put the entire thing a case so I could mount the banana adapters off the PCB where they could be farther apart. Not necessary but preferred for me.
Second, putting artwork in copper on your PCB not only works but looks great when you are finished. Take a look at the second photo below. That Freeside logo looks awesome!
Third, assembly of through hole components is NOT easier than surface mount parts. It was a bit of a pain to build them all. TH components don't stay in place when you flip it over to solder. 
Final PCB I used.
Artwork in copper.


Queued up for soldering.
Delivered and installed.

My lab's version with voltmeter and case.

It includes a cooling fan.


Eagle Files
Code uploaded to the ATTINY85. It includes the RotaryEncoder lib I posted earlier.
#include <RotaryEncoder.h>;
int del=0; 
word outputValue = 0;
byte data = 0;
int val = 0;

int csPin = 0;
int sckPin = 1;
int siPin = 2;
int ENC_A = 3;
int ENC_B = 4;
RotaryEncoder encoder(ENC_A,ENC_B,5,6,1000);
void setup()
{
  pinMode(csPin, OUTPUT);
  pinMode(sckPin, OUTPUT);
  pinMode(siPin, OUTPUT);
  setDAC(val);
}
void loop()
{
  int enc = encoder.readEncoder();
  if(enc != 0) {
    val = val + (enc);   
    val = min(val,4095);
    val = max(val,0);
    setDAC(val);
  }
  delayMicroseconds(5);
}
void setDAC(int value) {
    outputValue = value;
    digitalWrite(csPin, LOW);
    data = highByte(outputValue);
    data = 0b00001111 & data;
    data = 0b00110000 | data;
    shiftOut(siPin, sckPin, MSBFIRST, data);
    data = lowByte(outputValue);
    shiftOut(siPin, sckPin, MSBFIRST, data); 
    digitalWrite(csPin, HIGH);
    delay(del);
}
void sinewave()
{
  for (int a=0; a<=4095; a++)
  {
    setDAC(a);
  }
  delay(del+25);
  for (int a=4095; a>=0; --a)
  {
    setDAC(a);
  }
  delay(del+25);
}


Raspberry Pi Headless Media Center


Greetings fellow Raspberry Pi enthusiasts. I have something pretty cool to share with you today. I've been wanting to use the Raspberry Pi for a media center since I first heard about it. When Newark finally told me I could order the Pi I jumped at it chance and then promptly left town on a family vacation. My nephew Isaiah, who I met up with in Alaska while we were on vacation, discussed the media center project and how to implement it. Upon his suggestion we settled on running VLC. I had assumed we would have to get some webserver up and running and figure out how to slave VLC to our wishes but that is largely built in already. It is called the VLC Web Interface (or VLC http interface). That made this project all the more simple.

Below is the process to install it. This process assumes you have a freshly flashed Raspbian Wheezy (7/15) image that has NEVER BEEN BOOTED BEFORE. This made the most sense for us as we assumed you would plop this guy down somewhere and not use it for anything else.
  1. Take a freshly flashed Raspbian Wheezy imaged SDCARD and put it in your Rπ
  2. Make sure your WIFI adapter is NOT plugged in.
  3. Plug in keyboard
  4. Plug in Ethernet cable connected to the Internet
  5. Plug in Rπ
  6. Raspbian will boot up to the setup screen
    1. expand_rootfs
    2. configure_keyboard
      1. Select keyboard that works for you (default is UK which is hard to use with a US keyboard) Images of this process are at the bottom of this post (its sort of long and tedious).
    3. change_locale
    4. change_timezone
    5. ssh
      1. enable SSH Server (not necessary but useful since its headless)
    6. boot_behavior
      1. So NO. You want to disable booting to the desktop
  7. Reboot
  8. Login as root. Type "root" at the login prompt.
  9. Enter the commands below. (downloads and executes an installer script written by my nephew)
    wget db.tt/rDy1S8Ga -O install.sh
    source ./install.sh
    
    It will prompt you the following things:
    Press zero to set output to auto, press 1 to force headphone jack, press 2 to force HDMI.
    
    I recommend you select 1 if you plan to use the headphone jack.
    Would you like to setup the GPIO relay [y/n]?
    Click Y if you want GPIO25 (pin 22) to go HIGH (3.3V) when VLC is playing. Pin 22 is positive and Pin 6 is GND. The numbering system is strange because it starts at 1. You want the third pins from the top and bottom on the outside. Refer to the photo below. SSR available at Amazon.com
  10. Would you like to install rtl8188cus WIFI drivers [y/n]?
    This is the driver for the WIFI adapter I selected. Available at Amazon.com
    This driver installer was acquired from the Rπ forum and used with permission.
  11. At this point the install actually begins. VLC takes a long time to download and install. Then, if you selected the WIFI drivers it will ask you a bunch of VERY IMPORTANT questions and PROMPT YOU WHEN IT IS SAFE TO INSERT YOUR WIFI ADAPTER. Please read and follow along. I found that if it pauses for a long time while it prompts you to wait for the adapter to blink and connect  a quick re-plugging in of the adapter gets the system running again. The WIFI driver script ends asking you if you would like to upgrade your entire Rπ. I say no.
  12. Unplug your ethernet cable (if you are using wifi).
  13. Reboot.
  14. Boot up screen will tell you what the new IP address is on Wifi. make a note of it. You can then use this address to talk to your Rπ from local devices on the network. You can setup a static IP if you desire by going to /etc/networks/interfaces and changing the
    iface wlan0 inet dhcp
    TO
    iface wlan0 inet static
    address *your ip*
    netmask 255.255.255.0
    gateway *your gateway ip*
    
    wpa-ssid "*your SSID*"
    wpa-psk "*your password*"
    
You can now find you VLC running at http://*ip address*/. If you want to see if from the actual Rπ you need to go to http://localhost:8080 but we went through the effort of updating the IPTABLES to forward port 80 to port 8080. The /home/pi folder is the default place it looks for music.

The GPIO stuff works by running a script that checks the VLC status stream and turns the pin on or off as necessary. I did this with one long shell command the executes every 300ms. There are no doubt many ways to do this, but I always liked AWK and | so that's how I did it (its below). You can find all scripts we wrote to make this work in the /root folder.

wget -qO- localhost:8080/requests/status.xml | awk '/<state>/ {if (index($0,"playing") > 0 || index($0,"paused") > 0) {print "echo "1" > /sys/class/gpio/gpio25/value"} else {print "echo "0" > /sys/class/gpio/gpio25/value"}}' | bash

One thing I should mention is that depending on your network speed, you may want to increase the buffering cache so you do not get skips during streaming playback. This is done by modifying the /etc/init.d/rc.local. Add the two caching arguments you see below (to the line starting vlc you'll find it in there somewhere)
su - vlc -c "vlc --intf http --daemon --disc-caching=20000 --network-caching=20000

These are some screen shots from the initial config. I found the keyboard part sort of confusing.

Roomba Wii Shield

I've been working on an Arduino compatible Mini USB Host board. Well, I've had it done for a while now. I've slowly been compiling a bunch of projects for it so I can give it a cool Kickstarter one of these days. To that end, I designed a dedicated shield for controlling a Roomba vacuum with a Wii remote controller so that it might make the entirety of the project more compelling.



I'd already written the firmware and tested it with a chopped and spliced up cable a few months ago. It worked well for a while but one day the entire thing shot craps. My belief is that the on board voltage regulators could not handle the 16V the Roomba outputs (too much voltage to drop with an LDO without good cooling). So, for the dedicated board I decided to put a TO-220 7805 regulator with a heatsink on it. That should protect the main board from damage. I also had the idea of using optocouplers to isolate the Roomba signals from the shield. Optocouplers are ICs that contain an internal LED that turns on when a voltage is applied. That light shines on a photo detector which creates a voltage on the base of BJT opening a channel for current to run. This means two circuits can communicate without having any conductors between them. They isolate distinct circuits in effect. This seemed unnecessary but the board just had enough room and the datasheet gave the impression it would work (foreshadowing).


I built it up and put it together and I got nothing. The multimeter tests I conducted gave me no guidance either. I put voltage on one side of the optocoupler and I get a voltage out on the other side, or so I though. I put it on the oscilloscope and once again learned the value of good tools. The scope showed me that the clear problem was that the optocoupler is slow to respond. It can handle changes at human speeds but not a the speeds I was signalling. The initial speed was something like 300mS to drop off to 0V. That is glacial! The datasheet suggested 3µs was the expected value so I clear did something wrong. I read it closely and saw the RL needs to be 100Ω for that to work like that. 



Time for a little rework.


I bodged up the board and got the voltage dropoff speeds into the 25µs range and was hopeful. I plugged it in and ended up with a Roomba that was, well, drunk. It moved slow and listed to one side. No dice.

I grabbed another board from the bag and built up a fresh one wiring around the optocoupler.



I bundled it up and gave it to my son Zev. Have fun son.
 

First flight of the Hexacopter!



It's been a difficult journey, but we finally got the first flight of our DIY Drones Hexacopter. A special thank you goes out to the whole UAV team at Freeside Atlanta for donating their time, money, and resources to this project.

 Slade, who did several hours of last-mile troubleshooting to get the UAV in the air, is flying it by hand. Check out the video on Youtube, which shows us testing the pitch, yaw, and roll of the unit and finally getting flight. We were pretty surprised at how smoothly it flies.

Stay tuned, as we'll be setting up and configuring the UAV controls so that it can follow GPS waypoint flight paths. We're also going to be posting another video that explains how everything works, how we did the troubleshooting on the initial flight, and some new in-flight footage.

Constant Current Dummy Load - continued


Since the last installment, I've finalized the initial PCB design and sent it off to Seeedstudio for fabrication. I've never designed a through-hole (TH) construction board before but in general all the same rules apply to SMD and TH boards I believe.

200W 0.1Ω load
 
30W 1Ω load
10x10Ω 3W in ||
25 turn
trimmer pot
I changed up a few things during the PCB design phase of this project that I thought would be interesting to mention. I added a pair of trim pots to design. One trim pot reduces the maximum voltage going into the first op-amp stage. The second is the in the feedback loop of the first op amp stage. At maximum resistance, 3000Ω to GND (R2 of the voltage divider), with the 820Ω R1 (there for its role as a low pass filter in addition to the voltage divider), I should see a 27% voltage gain. Turned down to 0Ω, that pot creates a situation where the output is the high output voltage of the op-amp (essentially infinite gain). Something like 8V for the op-amp/input voltage I am using. Why did I bother to design a mechanism to adjust the highest voltage output across the load down to200mV and up to 8V? Well, so I could use a bunch of different load resistors with this circuit and not have to worry about lighting anything on fire with the knob after setting trimmers to their "final" value. I 0.1Ω load resistor is going to burn 10 times the current of a given voltage than a 1Ω resistor so it occurred to me that having a flexible system made a lot of sense. I got the trimmers on ebay for a quarter each, so while they are much more expensive than a normal resistor, they save me having to build a different board for each load resistor. You can trim it up for a given load within a minute with just a multimeter.



Basic MOSFET operating voltage graph
I also included to a switch so the user can switch between operating the main current MOSFET in the linear region (aka triode mode or ohmic region) or in the saturation region (aka active mode or fully enhanced). You can operate the MOSFET in the ohmic region by applying a relatively flat DC voltage on the MOSFET gate below the saturation voltage. The MOSFET behaves like a adjustable resistor in this mode. When operated in the saturation region (by putting high voltage on the gate) the MOSFET channel has its lowest possible resistance it has to offer but as a result you need to switch it on and off in order to limit the current. I hypothesize that the MOSFET will run cooler at a constant current in saturation mode then it will in the ohmic region but it remains to be tested. I decided to offer both options in the circuit because I figure both have their objective value. I show the difference on the scope in the video above.

In addition to these admittedly minor hardware revisions I also created the previously posted rotary encoder library so I could have both fine and course control over the output current. Might as well take full advantage of the digital circuitry, right?

The two holes labeled "LOAD" top center of the PCB rendering below are points you can use to measure the voltage across the load. That number, with a little basic Ohm's Law calculus, will tell you the current going through your load. It will be a useful point to pull data for an analog panel meter. The boards should be here within a couple weeks and then I'll build a couple up and post them up. I'll also bring one to Freeside to put on the shelf. It's always handy to have a precision load when doing electronics work.

I added the Freeside logo in copper on the top of the board.
It will be interesting to see how that looks in real life.

Arduino Rotary Encoder Library with Velocity Sense


While working on the constant current load project I found that while nice, the multiple turns required to turn up the power up was a little annoying when you just wanted to hurry up and get to a high value. The standard solution is to have a "fine" and "course" knob. Since I designed the input in the digital realm it seemed like software was the obvious solution. Why not sense the speed the user is turning the knob and extrapolate the pace of change based on that input. It seems intuitive to me. I implemented it as a little C++ library that you can drop into your arduino/libraries directory.

Here is the most trivial implementation of the library.
#include <RotaryEncoder.h>;
RotaryEncoder encoder(A0,A1,5,6,1000);
void setup()
{  
  Serial.begin(57600);
}
void loop()
{
  int enc = encoder.readEncoder();
  if(enc != 0) {
    Serial.println(enc);
  } 
  delayMicroseconds(5);
}

Inside the library, the code counts the number of the sequential clicks in one direction within less than the time constant you pass in when you instantiate the object. In the above example, the selected time constant is 1000µs (the 5th variable). If the user waits longer than that amount of time the counter resets. If the user changes direction the counter resets. To determine the return value I divide the counter by the 4th variable you pass in, 6 in this case, and then multiply that by 5 (the 3rd  variable) and return that value. Turning anti-clockwise is the same except that I make it negative (multiply value by -1). So, if you turn the knob 30 times in a clockwise direction I will return (30/6)*5 or 25. Bear in mind that 30 times doesn't mean 30 detents of the encoder. Each encoder is different. The ones I have in my drawer return 4 times per detent, YMMV.

The library is available here.

In order for this to work, you need to have clean reads of the encoder (or it will reset the counter). To do this effectively, you really need to "debouce" the switch. I've never been able to effectively do this in software. I use 10000pF capacitors between the A pin and GND and B pin GND. This makes the circuit very well protected from bad reads. Furthermore, you need to check the value more frequently than it can change otherwise the quadrature signal will become out of sync and you will not know what direction you are turning.

Tonight (July 14th, 2012): Chili fundraiser for the Offroad Wheelchair Project

The Off-Road Wheelchair is a device that will enable a person of limited mobility to experience the outdoors. Freeside Atlanta is interested in putting our engineering skills to the test, and showing the world we can create anything we put our minds to. We have the space, the tools, and the talented people to make this happen - we just need your help to purchase the materials and make this project a reality. The idea originated with Robin Beattie, who participates in regional Burning Man events, like the Alchemy Arts Festival here in Georgia. The festival takes place on a farm, with terrain features like gravel, light mud, paths with tree roots, and moderate changes in elevation. The Off-Road Wheelchair will be designed to traverse this environment, enabling Robin to get around in a place that would normally be closed off to her and others with limited mobility. Upon completion, the Off-Road Wheelchair designs and notes will be released under a Creative Commons (by-nc) license, which means that anyone can continue to contribute improvements on the basic design, so long as it remains for non-commercial purposes. The hope is that the Off-Road Wheelchair can be replicated at other regional Burning Man events, so that even more of the disability community can participate in this unique survivalist camping experience. This is our second fundraising round for the project. The first round of the project was at the Alchemy Arts Fundraiser, where we were the 3rd highest funded project of the evening, pulling in about a third of our requested project budget. This is a link to the Google Document describing the project, detailing the proposed budget, and outlining a few design ideas: https://docs.google.com/document/d/1ZLHe4XJtBqOgrQDVOkIZ0MtLGelBoQc-T4lL8dtgoAE/edit Our fundraiser will feature unique chili creations from the kitchen of Joy and Pain Cooking, plus possibly an auction of some kind, and possibly other fun surprises. Additionally, let me explain how the parking situation will work. This is Freeside Atlanta's page explaining how to get to the space: http://wiki.freesideatlanta.org/the-space The parking needs to happen towards the "back" of Freeside and the Metropolitan, so that everyone comes in through the rear garage doors. This is the marker called "Roll-up door access" in the embedded Google Map. Generally, in order to avoid a parking disaster, I recommended parking along the north and north-west part of the property. Please do not park in front of any garage doors (including Freeside's) as this puts you at risk of getting towed. Don't hesitate to email me if you need help getting there. You can email [masked] with the subject gatecode (one word). That will automatically reply with this month's gate code, if you need it. http://www.meetup.com/Freeside-Atlanta/events/70965732/

Constant Current Dummy Load

I just got my first oscilloscope. Complex analog circuits are now possible.



As I mentioned in my last post, I working on a power distribution unit (PDU) for motorcycles, cars, and other DC applications. The project is very close to the testing phase and that means I will need to run this device at precise power levels and at precise temperatures. The testing protocol also includes vibration studies, but today we are just going to talk about precision current testing.

This can be done many different ways. You can just put a resistor to ground and use Ohm's Law to tell you how much current you are burning. If you want to change the current in use though, you will have to change the resistor. That is not very handy if you want to test your power supply at multiple currents as you will need a lot of different resistors. Since my system is running at about 14V and I am talking about 15A of current, I'll need some pretty beefy resistors and those are expensive.

Instead, I've decided to purpose build a constant current dummy load. This uses a single logical load resistor (I will have parallel resistors but they will behave as one) and adjusts the voltage across it to define the current that gets burned. I searched Amazon and found a pair of 100W chassis mount 0.1Ω resistors for $7. My requirement for this testing tool is to be able to burn up to 15A which is the maximum current load I have defined for the device. Using Ohm's Law that means I'll need to to be able to adjust the output voltage between near 0V and 1.5V. If you put 1.5V across a 0.1Ω resistor you get 15A, so that is the plan. I have not done all the calculations necessary to nail down the exact output for a given input, but doesn't really matter because the input is linear from 0V to 1.5V and you will measure the output across the load and do your Ohm's Law calcs based on the precisely measured (4 wire) resistance for that specific load resistor. 200W is just a tad bit low (about 10W by the numbers) but I'll mount these on a heat sink with a fan around if necessary.


There are a couple of options I could select to get 1.5V on the output. I could use a voltage regulator to get a "precise" voltage, but that isn't really a good option. Regulator's are not that precise. Instead I'll use a voltage reference. The one I had in the drawer was a 2.048V reference and I can count on it to output exactly that figure. It is a high impedance output though so I'll need to do something else with that. I could setup an op amp and voltage follower and have a low impedance voltage source. With that, the standard thing to do would be to put a voltage divider in the circuit with a potentiometer to adjust that output to another op amp and put an output transistor in that amps feedback loop. I've decided to NOT do this though. I don't have any nice pots (10 turn or 1 turn), so I've decided to doing something with some digital components as well. I've decided to use a DAC (an MCP4921) to produce the voltage, based on the aforementioned reference. To control the DAC I need a micro-controller. I had a tube of ATTiny85 MCUs and that is just perfect for my needs. The ATTiny85 is an 8 pin MCU with 5 IO, Vcc, GND, and reset pins. The DAC requires 3 pins as it uses an SPI interface. That leaves me 2 pins to the human/machine interface. I have a drawer full of rotary encoders (like a digital pot). It outputs a quadrature code which essentially tells you what direction the knob is being turned. The MCU keeps track of the current state and adds or subtracts based on the encoder input and then sends a command to the DAC to change its output. 


My DAC is referenced to 2.048V and it is 12bit so it will output a linear voltage between near 0V and 2.048V at 4096 equal steps. Since I want only 1.5V I'll put a static voltage divider in the circuit and send that to the op amps which are controlling the output transistor.


I've seen a couple projects like this on the internet and they all used a system to control the output transistor that I don't like. They use a MOSFET which I like, but they simply bias the transistor in it's Ohmic region so that it is being used as a variable resistor. That causes the MOSFET to produce a lot more heat than if it were being run fully "enhanced" or "saturated" (we are talking about N channel enhancement MOSFETs). If you fully enhance it, power flows through it at lower resistance and your MOSFET will run cooler. It also means your analog circuit will need to be able to do fast, and preferably rail to rail, switching to keep the current constant. If fast rail to rail switching is what you need, then a comparator is a good thing to use.


I am using three op amps in the output transistor loop. The DAC feeds a voltage follower op amp and its output feeds the positive input of another. It's output feeds the positive of a third whose output drives the gate of the MOSFET. The MOSFET output runs into the negative terminal of the latter two op amps. This gives me a rail to rail PWM signal to the gate of MOSFET such that for each .1V I put into the first op amp, 1A goes through the load resistor. A nice system and my MOSFET runs as cool as possible.


This is the first analog circuit I've designed and built. It was made possible by the introduction of an oscilloscope to my lab. I like it! You can see my love of digital electronics has not died by my introduction of the MCU and DAC to a circuit that could have been done just as well with a nice 10 turn pot. No matter, the encoders are a dime a dozen and small while 10 turn pots are pricey and large.

Another challenge faced in this project is the fact that I am running an SPI device on an ATTiny85. This is worth mentioning because the ATTiny doesn't have a hardware SPI interface so it needs to be done in software. I didn't see any examples of this on the interwebz, so I'll post it up here in case it's is of use to anyone. I should also mention that the DAC I am using is a MCP4921 in case someone searches for a way to use this chip with a ATTiny they won't have to reinvent this wheel. The important things to notice are the use of the word (16 bit number) and the shiftout, highbyte, and lowbyte functions I am employing. These are built into the Arduino tool chain so as long as you can handle your latch pin by yourself you are in business.

int del=0; 
word outputValue = 0;
byte data = 0;
int val = 0;

int csPin = 0;
int sckPin = 1;
int siPin = 2;
int ENC_A = 3;
int ENC_B = 4;
void setup()
{
  pinMode(csPin, OUTPUT);
  pinMode(sckPin, OUTPUT);
  pinMode(siPin, OUTPUT);
  pinMode(ENC_A, INPUT);
  pinMode(ENC_B, INPUT);
  digitalWrite(ENC_A,HIGH); //these pins do not have pull up resistors on an attiny...
  digitalWrite(ENC_B,HIGH); //you must pull them up on the board.
}
void loop()
{
  int enc = read_encoderJOM();
  if(enc != 0) {
    val = val + (enc*10);
    val = min(val,4095);
    val = max(val,0);
    setDAC(val);
  }
  delayMicroseconds(50);
}

void setDAC(int value) {
    outputValue = value;
    digitalWrite(csPin, LOW);
    data = highByte(outputValue);
    data = 0b00001111 & data;
    data = 0b00110000 | data;
    shiftOut(siPin, sckPin, MSBFIRST, data);
    data = lowByte(outputValue);
    shiftOut(siPin, sckPin, MSBFIRST, data); 
    digitalWrite(csPin, HIGH);
    delay(del);
}

int oldENC_A = 0;
int oldENC_B = 0;
int8_t read_encoderJOM() {
  int a0Pin = digitalRead(ENC_A);
  int a1Pin = digitalRead(ENC_B);
  int returnVal = 0;
  if(a0Pin != oldENC_A || a1Pin != oldENC_B) {
    if(oldENC_A == a1Pin && oldENC_B != a0Pin) {
      returnVal = -1;
    } else if (oldENC_B == a0Pin && oldENC_A != a1Pin) {
      returnVal = 1;
    }
    oldENC_A = a0Pin;
    oldENC_B = a1Pin; 
    return returnVal;
  } else {
    return 0;
  }
}

Entire circuit except for the output transistor and the load resistor. Those are visible in the video above.

Yellow is output from DAC. Green is the final output to the MOSFET gate. The DAC is outputting 1.47V (the scope is off by a factor of 10) and the meter tells me the load resistor is burning 17A. The op amps are running at 12.5V and peak the peak the PWM is 12.4V. There is lots of room in that duty cycle as well you can see.