Tag Archives: DIY

Arduino MPPT Solar Charger Shield – Software

There have been two previous posts on this project: one on the concept and the hardware and one on hardware testing. You probably want to check them out first if you’re not yet familiar with this project. Or even better: Click here for an overview over this project.

20160212_Projekte_045
Maintaining an input voltage of 17 volts even if that means a lower-than-desirable voltage at the output

Now that we know that we have a functioning MPPT solar charger we are ready to talk about the software (or the sketch as the Arduino folks call it). It’s quite simple, really. So this will be a short post. And yes, you can download the sketch. There is a link at the end of this post. As always, I appreciate any feedback, comments and the like.

There is a number of basic tasks the arduino needs to perform in order for this shield to be useful. I’ll go through them one by one.

Controlling the DC-DC converter

At the heart of this project there is a synchronous step-down (or buck) DC-DC converter that is controlled by a PWM signal from the arduino. So one of the tasks is to set the frequency and duty cycle of that PWM signal.

We let the PWM signal run at the maximum frequency the arduino allows with an 8 bit resulution. Thats simply 16MHz (the Arduino’s frequency) divided by 256 (the 8 bit resolution), or 62.5 kHz. So the prescaler will be 1.

As you can see from the shields’s schematic, we need to output the PWM signal from Pin 6 (by the Arduino’s pin numbering, not Atmel’s). In order to do this kind of low-level stuff you’ll have to read the Atmega328’s data sheet. There is usually no Arduino-ish shortcut if you really need to controll what’s going on.

Luckily it’s just a few lines of code to set things up. All in the function buck_setup(). There are three more little functions to control the DC-DC controller once it’s set up:

buck_enable() and buck_disable() are very simple and just turn it on  and off, respectively. buck_duty(uint8_t duty) is only slightly more involved. It changes the duty cycle to the value you pass to it. Besides that it ensures that the duty cycle stays within certain limits.

20160212_Projekte_042
Test setup with resistor-based dummy load

You don’t want it to go to 100% since in order to keep the bootstrap capacitor C6 charged you need a little bit of off-time. In order to drive the upper FET you need a voltage higher than the panel’s voltage and that’s exactly what C6 is for. So we enforce an upper limit on the duty cycle.

Likewise, you don’t want your duty cycle to go below 50% because in that case you would be pumping energy from the battery to the pannel. A synchronous step-down converter is basically the same thing as a synchronous step-up (aka boost) converter with input and output confused. So we also want to enforce a lower limit on the duty cycle.

The upper and lower limits are set through the #defines DUTY_CYCLE_MINIMUM and DUTY_CYCLE_MAXIMUM.

Measuring voltage and current

The shield has all the hardware necessary to measure both voltage and current both at the input as well as on the output. We’ll just need to write some simple software to make good use of that hardware.

Unlike with the PWM singal where we had to do some low-level bit fiddling ourselfs we can just rely on convenient Arduino library functions to do the job. Basically, analogRead() is all we need here.

20160212_Projekte_043
Nicely regulating so that the input stays at 17 volts

I’ve written a function called read_values() that uses analogRead() to read all 4 values (input voltage, output voltage, input current and output current) 16 times each, averages the results and converts the ADC reading to proper voltages and currents.

The necessary multipliers are defined as floats in VIN_MULTIPLIER, VOUT_MULTIPLIER, IIN_MULTIPLIER and IOUT_MULTIPLIER. I’m doing all the voltage and current measurements in floating math. Yes, this is not at all efficient but we don’t need the Arduino’s computational power for anything else most of the time so this is fine here. Just keep in mind that you can save a lot of resources here if you ever need to do so.

Displaying voltage and current on the LCD

Our hardware also involves a 2 lines x 16 characters LCD so we can show the world what we are measuring. Again, we can rely on standard Arduino functionality to do the job. There is an LCD library that does everything we need.

So my function write_display() can focus entirely on formatting. The upper line shows the voltages in Volts, the lower line shows the currents in Milliamps. The input is on the left hand side of the display, the output on the right.

Deciding what to do

In the first section we’ve discussed the functions necessary to controll the DC-DC converter. But in order to use those functions, the Arduino needs to first decide what to do.

Vin21
66% duty cycle at 21V input voltage gives the desired 13.8V at the output

This is where the function buck_update() comes into play. You could consider this the heart of this sketch. This is where all the relevant decisions are made. When to turn the converter on, when to turn it off, when to increase the duty cycle, when to decrease it… You get the idea.

The behaviour of buck_update() is controlled by 8 #defines. I list them here together with the values I have used:

#define ENABLE_VOLTAGE 18.0
#define DISABLE_VOLTAGE 15.0
#define INPUT_TARGET_VOLTAGE 17.0
#define OUTPUT_TARGET_VOLTAGE_LOW 13.8
#define OUTPUT_TARGET_VOLTAGE_HIGH 13.9
#define INPUT_CURRENT_LIMIT 2000.0
#define OUTPUT_CURRENT_LIMIT 3000.0
#define INPUT_CURRENT_MINIMUM 0.0

I think they are quite self-explanatory, especially if you look at how they are used inside buck_update. It’s quite simple: If the panel’s voltage rises above 18V, turn the converter on. Once the converter is on, try to archieve a panel voltage of 17V without exceeding 13.9V at the output. If the panel’s voltage drops below 15V turn the converter off again.

Vin17
At 55% duty cycle with a 16.9V input voltage we’re getting only around 9.2V at the output

Besides that the function is also looking at the input and output current and makes sure certain limits are not exceeded. But with a 30W panel it should never be possible to reach those limits anyway.

Putting it all together

Now all we need to do in the loop() function is calling read_values(), buck_update() and write_display(). Since writing to the LCD is quite slow we are only doing it every 32nd time we read the values and update the PWM signal.

With this sketch I’ve hooked the MPPT Solar Charger up to my lab power supply. (a Keysight E3645A, my newest toy *g*) and my extremely simple but occasionally useful resistor-based dummy load.

The enable and disable voltages are simple and work as expected. Maximum output volage is also not tricky. If the voltage at the output goes too high, the duty cycle is decreased and everything is fine again.

20160212_Projekte_041
There’s not much to photograph when you’re writing and testing software

More interesting was to see how the shield would regulate when faced with a limited current budget at the input. For that the supply was set to a voltage of 21V (about a 12V solar panel’s open-circuit voltage) with a current limit of 100mA to 500mA. That’s quite a nasty supply, quite a bit trickier to handle than a real solar panel. Try to pull just a bit too much current and the voltage will drop to zero…

Also, the resistors at the output are not a realistic load for the converter. A car battery will pull no current at 12 volts or so (unless overly discharged) but will quickly start to sink large currents when the voltage goes just a bit higher and the battery is charging.

But I think the setup is good enough to test the sketch. And it handles the challenge quite well. With all resistors on (i.e a 100/6 ohms load) and a 300mA current limit, the input voltage sits at 17V (our target input voltage) while 9.25V appear at the output. At 400mA, the output voltage rises to 10.7V with the input still at 17V. At 600mA the input is still at 17V but with the output now at 13.15V. If I take the current limit even higher, the output voltage rises to 13.82V but not any higher, just as we want. The input voltage rises to 21V (since this is a lab supply and not a panel) with a corresponding drop in current to 530mA.

20160212_Projekte_044
Quite realistic: The charger is pulling as much current as it can with the current limit at 530mA and reaches an output voltage just above 12 volts

I’m honestly quite happy with the project as it is now. The idea definitely works and I’m motivated to design a new, deployable version with some fancy features that will use much less power at the same time. I’ve already done quite some work on that new version but it will take another few weeks until I get to describe that project here.

Until then I will show you some other, smaller projects that I’ve already finished but didn’t have time to document yet. So you will first see a number of smaller, simpler projects over the next few weeks.

Before I forget: There’s the Arduino sketch for download. And click here for an overview over this project.

Arduino MPPT Solar Charger Shield – Testing

20160203_Projekte_004
First tests are being performed on the Solar Charger Shield

In my last post I’ve introduced a proof-of-concept Arduino solar charger shield. I went through the hardware as well as the way it works – or at least is intended to work. It was prominently linked on dangerousprototypes.com as well as some other sites and got quite a bit of publicity as a result. Thank you all for sharing this post.

By the way: here’s an overview over all posts on this project.

20160203_Projekte_001
DUT hooked up to my Constant Current Dummy Load

This time I’ll show you some results of the testing that I’ve done. The basic test setup is shown above: The solar charger is hooked up to my home-brew constant current dummy load, together with a pair of DMMs at the output in order to precisely monitor output voltage and current. For the input I’m relying on the lab supply to provide these measurements. And yes, the shield does its own measurements of both input and output currents and voltages. Once calibrated they are even quite accurate but I won’t rely on them for things as calculating the converter’s efficiency.

no_load_overview
Vin=17V, no load

But first we need to see if our converter works at all. As the scope screenshot above demonstrates – it does. For all the tests shown in this post, the input voltage was provided by a lab supply set to 17 volts. So we’re not yet testing the software and its capability to draw just the right amount of current.

no_load_closeup
Vin=17V, no load

As you can see, since the converter can draw any (reasonable) current at the input, it provides the maximum voltage (set in software) of 13.8V at its output. In order to do that, the upper FET is on approximately 80% of the time. The signals all seem nice an clean and there is no noticable ripple at the output at 1V/div and no load. And the switching frequency is 62.5kHz (16MHz / 256) as expected.

1Amp_closeup
Vin=17V, Iout=1A

At 1 Amp output current, the software has to increase the duty cycle somewhat to 82% (above) and even further to 84% at 2A (below). Besides that, everything still looks very similar under load conditions.

2A_closeup
Vin=17V, Iout=2A

In my last post I’ve raised the question if the FET driver’s dead time of 540ns according to the datasheet is not a bit excessive. Well, let’s look at the dead time on the scope. First of all we can observe that the dead time of the IR2104 is in line with the data sheet. I don’t have it in front of me right now to check the min/max specs but the measured 522ns seem reasonably close to the theoretical 540ns.

deadtime
The IR2104 has a built-in dead time of 540ns according to the data sheet. We’re measuring 522ns here – close enough.

From looking at the screen shot above, the dead time does seem a bit long. The reason dead time is introduced is to prevent shoot-through. If both FETs are on there is a short-circuit from the input to ground. Together with the input capacity and the FETs low Rds-on, very large currents could flow, possibly destroying the FETs and at least detoriating efficiency. So introducing a bit of time when both transistors are off seems reasonable. But too much of it also costs efficiency since current has to flow through the diode instead of the lower FET. The main reason for using a synchronous topology is to prevent this in order to gain efficiency. So obviously one has to find a balance. I think here we’re a bit far on the conservative side but never mind for now.

20160203_Projekte_005
Let some current flow

So now that our converter is working, let’s take a look at efficiency. I’ve measured the efficiency at output currents ranging from 100mA to 2.6A in 100mA steps with the input voltage at 17V. I didn’t use the sense-wires connections on the lab supply so I had to compensate for the voltage drop on the input leads manually.

20160203_Projekte_007
There was a drop of up to 220mV on the input leads so the voltage reading of the lab supply is not quite accurate

The results are quite impressive:

  • 95.5% @ 100mA (worst)
  • 96.9% @ 200mA
  • 97.9% @ 400mA
  • 98.1% @ 800mA (best)
  • 97.1% @ 1600mA
  • 95.7% at 2600mA

So the efficiency is constantly at a very high 95.5% and better over the entire current range of interest.

20160203_Projekte_008
This little dummy load is really useful

The resulting loss is less than 1.6 Watts @ 2.6A out. As a result, the shield never gets hot, even when running at this power level for a while.

Note that this is quite a bit more power than the converter was designed for. 37W as opposed to the 30W I designed it for. The FETs could even handle much more. The limiting factor would likely be the coil reaching saturation. Unfortunately my lab supply doesn’t supply any more than 2.2A so I can’t push it any further.

20160203_Projekte_006
Shield performs well even beyond 30W spec

 

One thing to note is that these efficiency figures don’t take into account the power consumed by the arduino, the display, the fet driver, current monitoring ICs and so on. This brings us to the last topic for now: The current consumed by the various components. I did these measurements mainly in order to understand how to limit power consumption in a later version. To me, this shield is only a proof of concept and so reducing power consumption was never an issue.

20160203_Projekte_002
Basic test setup

Here are the results:

  • Arduino: 48.7mA
  • LCD backlight: 8.9mA
  • LCD excluding backlight: 1.148mA
  • FET driver (standby): 106.56uA
  • FET driver (62.5kHz, Iout=0): 2847uA
  • FET driver (62.5kHz, Iout=2.5A): 2937uA
  • Current sensors (each): 48.6uA

So the arduino itself is using up the lion’s share of current. Next comes the LCD backlight. Nothing unexpected so far. The LCD without backlight still consumes a considerable 1.15mA, no matter if it’s on or off. The FET driver uses around 2.9mA when on and only about 0.1mA when off. Output current only has a minor impact. The current sensors don’t use up much – less than 0.1mA for both.

Check out my next post for a closer look at the software or here for an overview over this project.

Arduino MPPT Solar Charger Shield

20160119_Projekte_028

A friend has approached me regarding his solar project. He wants to install a solar panel together with a battery and an inverter in order to have power at his allotment garden. He had looked at a hobbyist project where an arduino was used to build a MPPT (maximum point of power tracking) charge controller. I took a look at the design, liked a lot of what I saw and decided to build something similar.

20160119_Projekte_032

The basic idea behind an MPPT solar charger is simple. A solar panel has a certain voltage (in the region of 17 to 18 volts for a 12 volts pannel, somwhat dependent on temperature) at which it provides most power. So as long as the battery needs charging, you want to pull just as much current to reach this voltage. But once the battery is full you need to avoid overcharging the battery. So you want to maintain a maximum voltage for your battery (somewhere around 13.8 volts for a 12 volt lead acid battery) and no longer care about the pannel’s voltage.

20160119_Projekte_029

So the charger needs to convert an input voltage of 17-18V to an output voltage of 12-14V as efficiently as possible. Obviously, a step-down (aka buck) switching converter is ideally suited for the job. However, a typical DC-DC converter is designed to maintain a stable voltage at it’s output, independent of it’s input voltage. As described above, our requirements here are different.

20160119_Projekte_038

Switching converters are controlled by the duty cycle of a (typically) fixed-frequency PWM signal. So a microcontroller could be used to do the job. In most applications, this wouldn’t work that well because a microcontroller would be too slow to react to sudden changes in load or input voltage. But this is not much of a concern in our solar application: Sun intensity changes within seconds at best and the battery will absorb any sudden changes in load. So if we adjust our duty cycle a few times per second we’ll be more than fine. And that’s easy to do with a microcontroller.

20160119_Projekte_030

The next step was to figure out at which frequency to run our converter. An arduino runns at 16MHz. At a 8-bit resolution, this gives us a maximum PWM frequency of 62.5kHz. That’s a pretty slow speed for a switching DC-DC converter nowadays. Most modern designs run in the hundreds of kHz to a few MHz. The main reason of using higher and higher switching frequencies is size. The higher the frequency, the smaller the inductor can be. For us, using a somewhat bigger inductor is totally acceptable. And in terms of efficiency, a lower frequency is even preferable since it reduces switching losses.

20160119_Projekte_037

The project here is intended mainly as a proof on concept. I expect it to be fully functional but it will consume quite a bit of power while sitting idle. The display (including backlight) is always on, the same goes for all the other components. But the main drain on the battery will be the Arduino itself which consumes around 50mA when running at 16MHz. That might not sound like much but it will add up during the many hours the solar panel doesn’t produce any power. The system will be installed in Zürich, Switzerland so you can’t count on having 8 hours of sunshine every day. In winter, there might be snow on the panel, preventing it from producing anything for weeks in an extreme case. So a productive system should draw hardly any current (say <1mA) when not doing anything useful.

20160119_Projekte_031

At least for now, the we’ll be using a 30W 12V monocrystaline panel and a 45Ah car battery. So I’ve scaled this converter to comfortably handle 30W input power which translates to about 1.8 amps at the input and 2.5 amps at the output.

As deba168’s design, I’m using a synchronous buck topology. If you’re new to switchers, you might want to check out this wiki page. If you’re serious about designing your own you might want to read Sanjaya Maniktala’s ‘Switching Power Supplies A – Z’, it’s a great book. I’ve also read his other two books on the topic but this is the one I love the most, especially to start with. I’m also using the same half bridge driver (IR2104) even though I find the 540ns off time somewhat excessive. But I like the enable/pwm input signals as opposed to having to drive each fet individually and I found this feature to be somewhat rare.

20160119_Projekte_035

Apart from that I’ve really done my own design, mainly using parts I’ve still had from previous projects. As most stuff I build, it’s entirely SMD, except for the input and output capacitors. Not only are SMS designs smaller in size. The parts are much easier to source (and often cheaper) than conventional through-hole components nowadays. And contrary to popular belief, with a bit of practice I find them easier and faster to solder.

The FETs are IPB136N08N3, a quite large surface-mount type that I use quite frequently. They have a 11mOhms Rds-on resistance which will be great for efficiency. They are also easy to drive in terms of gate capacitance. Probably a bit oversized for the 2.5 amps we’re trying to switch here but I still have some here and they’re not expensive, around 70 cents each. The inductor is a 100uH Coilcraft MSS1583 with a resistance of 0.103 ohms and a 2.8A current rating. 100uH is a bit much at full load, 68uH would easily do. But the system will spend most time at moderate loads (remember, this is not California). I’ve ordered a 68uH as well and intend to use it for a later design or maybe to see what difference it makes. Input and output caps are quite a bit oversized as well, 680uF 35V at the input and 820uH 25V at the output. They are from the Panasonic FR series which I like using for my switchers since they work well at frequencies up to a few hundred kHz while being afordable and having very high ripple current ratings.

20160119_Projekte_034

I’m doing voltage and current sensing at both input and output. I’ve decided to use conventional high-side, shunt resistor based current sensing. The Texas INA213 are fairly precise, work up to 26 volts and have a fixed gain of 50. Also here, I still had some left over from my dummy load project. Most components are much cheaper if you buy 10 in stead of just one or two so I tend to buy 10 😉

I’ve also added a standard 2×16 characters LCD display so I can see what’s going on. And you may have noticed that I’ve put a zero ohms resistor at several places. This will enable me to easily measure current consumption of the respective sub-circuit. As mentioned before, current consumption will play a major role in the final design so I’m interested to see how much juice is used by certain components under real-life conditions.

Besided the connectors for the panel and the battery, I have added a separate connector for the power supply. This is handy for early testing and programming. Just connecting this supply will power up the entire system. The arduino, the display, the converter and all. But there is not yet any load at the converter’s output and no supply at it’s input. So I can start programming the Arduino, start measuring and displaying voltages and currents and even turn on the converter to see if everything behaves as expected. And since there is nothing at the converter’s input and output, not much can go wrong. I don’t risk blowing up the FETs due to a bug in the program or a problem with the board. Only once I’m confident that everything works as expected I will connect a panel and a battery. At that point, the 12V input can just be connected to the battery as well.

20160119_Projekte_039

I’ve written a simple sketch for the Arduino that measures voltage and current at the input and output and displays the result on the LCD. Once the input voltage exceeds a certain threshold, it will enable the half bridge driver and start switching. It starts at a duty cycle that will produce an output voltage equal to the current battery voltage. That means that no current will flow to the battery yet so the converter can start up with no load. Once the switcher is turned on, the Arduino will adjust the duty cycle about 4 times a second. If the input voltage is above its optimum and the battery has not yet reached its maximum voltage, the duty cycle will be increased by 1/255. If either the battery voltage is too high or the input voltage is below its optimum, the duty cycle is decreased by 1/255. There are also some checks for overcurrent at the input and output.

20160119_Projekte_036

The switcher is turned off when the input voltage or the output current falls below a pre-defined threshold. This is a synchronous converter so current can flow back from the battery to the panel. We can’t just wait for the input voltage to fall. As long as the switcher is on, the input will never fall because energy is pumped from the battery to the panel. A synchronous buck converter is just the same as a synchronous boost converter with its inputs and outputs inverted. So we need to make sure current is actually flowing to the battery. Luckily, a car battery will always draw a clearly non-zero current at 13.8 volts, even when fully charged. So when current stops flowing to the battery, we know the panel is no longer able to provide any power and we can or rather must turn the converter off.

20160119_Projekte_033

This post ist getting rather long so I’ll stop here and will write another post later about how the circuit has been performing and what I have learned so far. I guess this project will turn into a little series, maybe with further (and hopefully improved) versions being developped. Looking forward to that.

Before I forget: Here’s the eagle files as well as schematic and layout PDFs as a zip file: SolarCharger_Rev1.

Update: Click here to see how the shield performs or here for an overview over this project.

Stand-alone Inductance Meter

_MG_1169

Some of you may have seen my arduino-based inductance meter in this post: http://soldernerd.com/2014/12/14/arduino-based-inductance-meter/. The guys at dangerousprototypes.com picked it up (http://dangerousprototypes.com/2014/12/16/arduino-based-inductance-meter/) and this blog got more visitors than I could ever have imagined. Thanks, dangerousprototypes.

_MG_1158

The arduino-based meter works well and made a great proof-of-concept. But for everyday use you’re probabely not looking for an arduino solution but rather something that looks and feels more like a multimeter. That’s why I’m following up with this stand-alone version.

_MG_1175

So this version is battery powered and comes complete with a 3D-printed case. It uses a mid-range PIC microcontroller, a PIC16F1936. Not that there’s much special about this model, I just happened to have some left from previous projects. I also thought about using a Atmel Atmega328, the same chip that is on the Arduino UNO.

_MG_1172

Using an entirely different chip means I’ll have to write the software from scratch. But I felt that the Atmega328 was just too much of an overkill just to measure a frequency and control an LCD. They are quite a bit more expensive than the PIC, CHF 3.70 compared to CHF 1.90 @10pieces at Farnell where I get just about all my chips.

_MG_1159

Talking of the LCD: The one I’m using here comes with a I2C interface. It’s blue with a white backlight and 2×16 characters and really tiny. I bought 2 of them years ago because they were small and relatively cheap (around 15CHF) and don’t require so many precious I/O pins of your microcontroller. Somehow I never used them but here their small size makes them a good choice. I/O pins aren’t a constraint here obviously as most of the 28 pins are unused.

_MG_1170

I’m not yet familiar with the details of how they are controlled. I had a look at the data sheet and it looks like you send them just about the same commands like with the standard Hitachi compatible ones, just over I2C. But I expect to spend an evening or two figuring out the details.

_MG_1173

The case was designed using FreeCAD. As the name suggest, it’s a free (and open-source) CAD design tool. This was only the second time I was using it but I found it quite easy to learn.

_MG_1162

I printed the case at the Zürich fab lab (zurich.fablab.ch) on one of their Ultimakers. Was my first 3D-printing project, thank you very much for your support, everyone.

_MG_1178

As always, I’ll put all the files online as a zip. So you can download all the Eagles plus PDFs as well as the FreeCAD models. Here it is: InductanceMeter. I haven’t written any software yet but I’ll but that online, too, as soon as it’s finished.

_MG_1176

The software is ready now. Klick here for the next post: http://soldernerd.com/2015/01/23/stand-alone-incuctance-meter-finished/.

Arduino-based Inductance Meter

_MG_1131
Incuctance meter in action. It displays the resonance frequency together with the inductance

I’ve just finished a little Arduino project. It’s a shield for the Arduino Uno that lets you measure inductance. This is a functionality that I found missing in just about any digital multi meter. Yes, there are specialized LCR meters that let you measure inductance but they typically won’t measure voltages or currents. So I had to build my inductance meter myself.

_MG_1146
Close-up of the circuit with the display removed

The basic design is really simple. It a colpitts oscillator (http://en.wikipedia.org/wiki/Colpitts_oscillator) with the coil missing. You use the test leads to connect it to a coil which will make it resonate. The Arduino then measures the frequency at which the oscillator is resonating and calculates the inductance. The capacitors are part of the shield so the capacity is known.

_MG_1132
With the test leads open, the oscillator can’t resonate. The current calibration/zero-offset is displayed in stead

There is 1uH of inductance included on the schield which is placed in series with the coil to be measured. This serves two purposes: The oscillator can resonate when you short-circuit the test leads. When you then press the push button on the shield, the software will use the current measurement as new calibration. It also puts an upper limit on the resonance frequency. This ensures that the software the rest of the circuit can keep up with the oscillator.

_MG_1139
Pressing this blue button zeroes the meter

As can be seen from the schematic, the oscillator uses two 1nF capacitors in series. Together with the 1uH inductance, this limits the frequency to about 7.1MHz. In practice, it oscillates at around 5.4MHz when the test leads are short-circuited.

_MG_1137
The Arduino shield from below

The oscillator output is followed by a comparator turning the sine wave of the oscillator into a square wave. I’ve used an inexpensive but fast Microchip MCP6561R. It has a maximum propagation delay of 80ns which allows it to keep up at the maximum frequency.

_MG_1142
Viewed from straight above

But of course, 5.4MHz is way too fast for the Arduino to keep up. The Arduino runs at 16MHz and will need at least a few dozend instructions to process each pulse from the shield. My solution was to add a 74HC590 8-bit binary counter dividing the frequency by 256. That gives a theoretical maximum frequency of 7.2MHz / 256 = 27.7kHz. That’s something the Arduino can deal with.

_MG_1145
The entire shield with the display removed

For obvious reasons, there is also a display included on the shield. And then there’s that pushbutton which is debounced in hardware by running it through an RC low-pass filter and a Schmitt-triggered buffer. The button is used to zero the meter, i.e. the current measurement is used as the new zero-offset.

_MG_1151
Even very small inductance values can be measured

All related files can be downloaded as a .zip file: LMeterShield. This includes the Arduino source code (aka sketch) as well as the Eagle files and PDFs of both the layout and the schematic.

Now there’s also a stand-alone version: http://soldernerd.com/2015/01/14/stand-alone-inductance-meter/

Arduino Ultrasonic Anemometer Part 9: A new hardware

My first wind meter prototype is kind of working. The software will need improvement to make this wind meter into something really useful. But both hardware and software are basically functional and can be built up upon.

If you’re new here, you might want to check out the overview over this series of posts on the arduino-based ultrasonic anemometer: http://soldernerd.com/arduino-ultrasonic-anemometer/.

_MG_1007
The new ultrasonic wind meter Arduino shield

The next thing I will do is re-design the entire hardware. Instead of two distinct boards with wires all over the place I will design a single, standard-sized Arduino Shield that can be stacked on an Arduino Uno. Just like any of those commercially available shields that add motor control, Ethernet or whatever. That will make the whole setup much smaller and simpler. And I hope this will also make it easier for others (like you?) who want to build their own.

This re-design is what I’m going to talk about today so I guess there won’t be much in the way of photos, just some schematics and board layouts. And I’ll put all the Eagle files on the overview page as a zip download. Here’s what I’ve changed and why:

Power supply

The first version used the (unregulated) Vin of the Arduino so it had a linear 5V regulator of its own. On top of that there was also a flying capacitor type inverter to generate a -5V rail for the analog multiplexer. Both of these chips have been eliminated. I’m now using the the 5V rail straight from the Arduino, there is just a 100uF tantal input cap. The -5V is no longer needed by the multiplexer. I’ll later explain why.

Signal routing / pulse generation / drive

The drivers are entirely new: I’ve replaced the two 74HC368 inverters with a single 74HC126 non-inverting line driver / buffer. It has four 3-state buffers, one for each transducer. The negative pin of each transducer is simply grounded in the new design. That costs us half the signal amplitude but simplifies things greatly. And our two-stage amplifier should have more than enough gain to make up for that.

As suggested earlier, there is only a single 74HC4052 left (instead of 3). We will get some crosstalk issues but we’re always transmitting or receiving, never both at the same time. Plus, the tuned amplifier filters out most of that high frequency stuff (such as square waves). And we have the option to mute the amplifier, this time both at the input as well as on the output. Not sure if we’ll need it, I’ll check once everything else is working.

Permanently grounding the negative pin of the transducers means we only have four signals to worry about. So I’m only using half of the 4052 to chose exactly one of the four signals. Y0, Y1, Y2, Y3 as inputs from the four transducers and Y as output that goes to the amplifier.

But why don’t I need the -5V anymore? Here is why. In my first design I routed the signal from the transducers straight through the 4052. Because this signal swings around ground, it will be negative half of the time and positive the other half. So I needed both a negative and a positive supply. Later, that signal was capacitively coupled into the amplifier where it was biased so somewhere around 2.3 volts. Now I already do the biasing before the 4052. So the signal will be positive at all times and hence there’s no longer a need for a negative voltage. I find this a really elegant solution, I just hope it will work 😉

There is still an Axis and Direction signal controlling a 74HC139 encoder generating the enable signals for the transducer drivers / output buffers. I had LEDs on these enable signals in the first version, these are no longer present. The software changes the axis/direction every 2ms so you won’t be able to see anything now.

The 74HC126 has active high enable signals (as opposed to the 125 which is otherwise identical). Since all but one enable signals are high, only one transducer can float freely. That’s our receiving transducer. That also means that the other 3 transducers are actively driven so only one of them must receive the PWM signal.

This is how I’ve solved this: As I said, I only used half of the 4052 for the tranducer signals. So the other half can be used to route the PWM signal from the Arduino to the correct output buffer. So the signal from the Arduino is connected to the input X and the outputs X0, X1, X2, X3 carry the signal to the different gates of the 74HC126. There is one potential problem: The outputs that are not selected are floating freely so there are 10k pull-down resistors on X0, X1, X2 and X3.

So from the 8 large ICs on the first version, only 3 are left. That saves plenty of board space so we can fit our circuit on a standard sized Arduino shield.

_MG_1008
Same board from the other side

Amplifier

The basic design with two stages of tuned common emitter amplifiers with NPN darlington pairs has worked well so I’ll stick to that.

The main shortcoming of my first version was the 47uH plus 330nF LC tank (see part 4) so I’m changing that to 1mH plus 15.82nF. Same resonant frequency but much higher impedance. The inductor I’ve chosen has a dc resistance of a bit more than 16 ohms which will give a Q-factor of around 15 – comfortable for our application.

The main change is the biasing. A wind meter will be deployed outside so it is likely to see great variation in temperature. So the biasing of our amplifier and thus the quiscent current need to be stable over a wide temperature range. Two things make this a difficult task here: First, we’re using darlington pairs which means twice the variation in base-emitter drop. Second, our rather low operating voltage of 5 volts.

A common solution for difficult biasing situations is the use of a matched transistor to generate the base biasing voltage. And that’s what I’ll do here. Each stage has an additional darlington pair with collector and base connected for this purpose. So the collector will always be 2 diode drops (around 1.3V at room temperature) above its emitter. I want the emitter to sit 1V above ground and 1mA of quiscent current. So I add a 1k emitter resistor and a 2.7k collector resistor and get just that.

Base emitter drop will change by about -2mV per degree per transistor. So for a 50 degree increase in change in temperature, the drop accross our darlington pair will change from 1.3V to 1.1V – quite substantial. But quiscent current will only increase to 1.054mA and the emitter will then sit 1.054V above ground. A 5.4% variation for a 50 degree change in temperature. Not bad at all I think.

The last change to the amplifier is that I’ve put the gain limitting resistors (R7 and R12) in series with only the bypass caps (C5 and C10).  This will let me change the gain without affecting biasing which is given by R8 and R13.

Zero Crossing Detector (ZCD)

Almost no change here. I’ve only changed my comparator to be a Microchip MCP6561R. It has a worst-case propagation delay of only 80ns which is 100 times faster than the one I used last time. And it’s still cheap: CHF 0.43 at Farnell if you buy 10.

Envelope Detector

I told you earlier that I had some trouble with my last envelope detector which utilized a VCVS active low-pass filter. If I turned up the gain too much I got wild output swings. I found a screen shot of that:

send_receive2
Envelope going wild

Green is the amplifier output. We’re trying to get the envelope of that. But look what happens to the pink line when I turn up the gain. Nothing to do with an envelope. And I would like even more gain to make the envelope use (almost) all of the 0…5 volts range.

I haven’t really understood why that is. Suggestions anyone? The only thing I can think of is the rather narrow gain-bandwidth product of the op amp, 600kHz if I remember correctly.

So I’m using two op-amp buffers, each followed by a normal RC low-pass filter. So I can set any gain I want for the two buffers without affecting the signal shape. As an added benefit, I can now look at the signal after each buffer / filter. I’ve also changed the op-amps to be Microchip MCP601R. Less precise (we don’t need precision here) but fast (2.8MHz) and cheaper.

At the very input of the envelope detector I’m now using a second (not really matched but same type) diode (D2) to produce a bias voltage just a diode drop above ground to precisely compensate for the rectifying diode (D1) of the envelope detector.

The comparator at the output is now a MCP6561R as for the ZCD. Not that we need the speed here, just to use the same type.

Temperature measurement

Everything new here. LMT86 as a temperature sensor. Cheap, works from -50 to +150 degrees centigrade and is accurate to 0.4 degrees. Its output is between 1.5 and 2.5volts over the temperature of interest. It comes in a SC-70 package. That’s a bit small but still hand-solderable without problem.

There is no more op-amp to scale it up but I’ve added a rather precise 2.5V voltage reference, the ADR361. Quite an overkill maybe but I thought if you are measuring wind speed you are likely to also measure things like humidity, pressure, light intensity or something like that. So with the anemometer shield you get a precise and stable reference for all your measurements.

Summary

As you can see, I ended up changing quite a lot. When laying out the board I was surprised how easily everything fitted in. Not only did the fewer logic ICs save space themselves, it also greatly simplified signal routing. As you can see from the photos, I’ve already made a board. All the components have arrived as well so I’m ready to go ahead and build it up. I’m really looking forward to seeing how it will perform. I just hope everything works as planned.

All the board and schematic PDFs as well as the Eagle files can be found on the overview page as a .zip file: http://soldernerd.com/arduino-ultrasonic-anemometer/

That’s it for now, click here for the finished shield: http://soldernerd.com/2014/11/28/arduino-ultrasonic-anemometer-part-10-arduino-shield-ready/

Arduino Ultrasonic Anemometer Part 8: More Software

In my last post I talked about how to get the Arduino to output bursts of 40kHz pulses. Today I’ll go through the rest of the software so by the end of this post we’ll have a very rudimentary but working sketch for our ultrasonic wind meter.

Click here for an overview over this series of posts on the Arduino Ultrasonic Anemometer: http://soldernerd.com/arduino-ultrasonic-anemometer/

overview2_1ms
Overview over one round of measurements, i.e. each direction is measured once in turn.

If you’ve read part 7 of this series you will have noticed that all the key tasks are handled not in the main code but in interrupt service routines (ISRs). That’s fairly typical for an application like this one.

In this project, there are 2 ISRs:

  • TIMER1_COMPB Interrupt: It is triggered by Timer/Counter1. It sends 15 PWM pulses every 2ms and takes care of the Axis, Direction and Mute signals. Named TMR_INT on the screen shots in this post. This is what I’ve covered last time.
  • TIMER1_CAPT Interrupt: This is where all the measurement takes place. It is triggered by the envelope detector and zero-crossing detectcor. It reads the current value of Timer/Counter1. Named CAPT_INT on the screen shots in this post. This is what I’ve covered last time. This is mainly what I’ll be covering today.

The basic Idea of the software is as follows:

  1. Every measurement takes 2ms. It takes 375us (15 times 25us) to send the pulses plus 500us – 1500us for the pulses to arrive (assuming very extreme wind situations). So 2ms gives us plenty of time to finish our measurement.
  2. Shortly after sending the pulses we start listening and wait for the envelope detector to trigger TIMER1_CAPT interrupt. We save the current value of timer1, this is our coarse measurement of time-of-flight. We then set up interrupts to capture a rising edge of our zero-crossing detector (ZCD).
  3. A rising edge of our ZCD triggers TIMER_CAPT interrupt. We save the current value of timer1 and set up interrupts to capture a falling edge of the ZCD.
  4. A falling edge of our ZCD triggers TIMER_CAPT interrupt. We save the current value of timer1 and set up interrupts to capture a rising edge of the ZCD.
  5. Repeat steps 3 and 4 until we’ve captured 8 rising and 8 falling edges. Averaging these will give us a very precise measurement of the phase shift.
  6. After every measurement we change the direction we measure:  N->S, E->W, S->N, W->E, …
  7. We measure each direction 32 times until we calculate the actual wind speed. So one full measurement will take 4 x 32 x 2ms = 256ms. So we take about 4 measurements per second.
overview2_172us
Overview over a single measuement

The screen shot above shows how a measuement proceeds: AXIS and DIRECTION are set depending on the direction to be measured. MUTE is driven high and 15 PWM pulses are sent. TMR_INT  triggers after every pulse in order to count them. After a short break, TMR_INT triggers again and turns MUTE off again. Eventually, the envelope detector (ENV_DETCT) triggers CAPT_INT. Shortly afterwards, CAPT_INT is triggered 16 more times by the zero-crossing detector (ZCD).

overview2_35us
Close-up of the actual measurement.

There are 2 sets of variables to save all the measurements from the envelope and zero-crossing detector: At any point in time, one is in use by the ongoing measurements, i.e. they’re being updated. The other set represents the last set of measurements and is static. This second set can be used by software in our main loop to calculate the wind speed and direction. As I’ve said, capturing one set of measurements takes 256ms. So we also have 256ms to do all the calculations, send data (via USB or whatever), write the new measurement to the display, do some data logging or whatever else we have in mind. There is likely to be some floating-point math, square roots and tigonometric functions going to be needed to arrive at the wind speed and direction but 256ms should be pretty comfortable even for that.

overview2_8ms
A long series of measuements. Look at the cursors: It takes about 25ms to do our calculations.

This is what I’ve tried to show in the screenshot above: There is a signal named CALC which is driven high when a new set of measuements becomes available and driven low when the calculations are finished. So this signal shows you how much time the Arduino’s Atmega328 spends processing the data and writing to the display. As you can see, it’s less than 25ms so there is ample of room for more complex calculations or other tasks. We’ll definitely need some of that head room since the calculations performed so far are really just the bare minimum.

There definitely is still a lot to be improved, mainly how the raw measurements are evaluated to get the actual wind speed. But what’s more important to me at this time is that the basic idea/setup works. With no wind, my measuements fluctuate somewhere between plus/minus 0.3 meters per second without having done any calibration. It also reacts nicely when I blow a bit of air towards it.

I’ve changed the pinout many times while developing this software but I’m confident that I won’t have to change the pinout any more. So my plan is to now build version 2 of the hardware first. The entire setup will be much less complex (and prone to errors) without all the lose wires going back and forth between the different boards. Then, with the updated and hopefully final (or nearly final) hardware I’ll go ahead and finish the software.

Speaking of software: You can download the Arduino sketch from the overview page where you also find the Eagle files for both boards: http://soldernerd.com/arduino-ultrasonic-anemometer/. I’ll make it a habit to post all the download material for this project on the overview page so people don’t need to go through all the posts trying to find a certain file.

That’s it for today, continue here to my next post of this series: http://soldernerd.com/2014/11/25/arduino-ultrasonic-anemometer-part-9-a-new-hardware/