Tag Archives: PIC

Programmable LED Dimmer

Around one and a half years ago I’ve designed and built various LED dimmers for both white and RGB LEDs.  Then late last year someone approached me asking if I could make an RGB dimmer for him, too. But my designs were really tailored to their specific applications and built with home-made, i.e. milled PCBs which are time-consuming to make. So I decided to make a more universal version based on a proper, etched board which could be built in a small series and used for all kind of applications, both white and RGB. The result is this versatile, programmable 4-channel dimmer.

The design is based on my previous RGB dimmer but with a number of improvements.

soldernerd.com is now on YouTube

I’ve just uploaded a short video showing this device in action. Here’s the link: https://www.youtube.com/watch?v=ehZybd3Y2kc. This is only my second video so don’t expect miracles but I’d be interested to hear if you would like to see more videos in the future or if you prefer the traditional text and photos format.

Wide voltage range

It now operates from any voltage in the range of 6 to 26 volts as opposed to 12V only. In order to accomodate such a wide range of inupt voltages the regulated logic level voltage of 5V rather than the inupt voltage is now used to drive the mosfets.

Extremely low standby current

This 5V rail is generated by an LM2936 linear regulator with a very low quiscent current and shutdown input. That allows for a nice power saving feature for when all the outputs are off. After a few seconds of sitting idle the entire device powers itself off, i.e. it turns off the LM2936 thus only consuming 30 microamps (typ.) plus some leakage in the capacitors. So the device can stay connected to a battery for months without draining it. To wake it up one has to press any of the two push buttons.

Rotary encoder design options

Talking of push buttons. Like my previous RGB dimmer it features two rotary encoders with push buttons.

But now there are two different types of encoders that can be used.
The ones previously used with their axis perpendicular to the board and a different type where the rotary axis is parallel to the board.
And either type can be mounted on either side which gives you even more freedom for your physical design.

Perfectly debounced switch signals

As always with my designs, the signals from the encoders (six in total) are nicely debounced in hardware by running the RC-filtered signal through a 74HC14 schmitt-triggered hex inverter. So the singals are perfectly clean when they reach the microcontroller.

Noise immunity

With my last design I had experienced some difficulties with ground bounce or insufficient ground connections in general leading to less-than-reliable encoder readings. It’s always more difficult go ensure good, low impedance ground connections on those prototype boards since there are no plated-through holes and vias. On that prototype board the issue was solved by soldering in a few short pieces of wire where the ground connection needed improvement.

So with this new design I paid very close attention to ground. I spent a lot of time working on the board layout to ensure that everything is as noise immune as possible. I always use ground vias generously but here I really tried everything to get the best, shortest and lowest impedence ground connections could get. I’ve also used decoupling capacitors even more lavishly than I usually do.

New microcontroller

I’ve changed the microcontroller to a PIC16F18325 which is smaller and cheaper than the previously used PIC16F1936.
The 18325 has become my standard choicer whenever I need a low pin-count microcontroller. I particularly like its remappable pins which give a lot of freedom to simplify your signal routing on the PCB.

Smaller size and more outputs

The mosfet drivers are basically the same as before but now with non-inverting outputs: LM5111-1M. There are two of them for a total of 4 outputs compared to only 3 with the previous version.
They now drive much (physically) smaller but no less capable mosfets which allowed me to significantly downsize the whole board to 75x65mm.  The NXP BUK9Y12-40E are rated at 40 volts and offer an on-resistance of 12 milliohms (max @ 25 degrees ) with a 5V drive as we have here. Their large thermal pads a the bottom (NXP calls that package LFPAK) pass heat efficiently to the PCB which then serves as a heat sink. There is also a 30V version that offers even better performance but with a maximum input voltage of 26 volts I thought the 40V version is the safer choice.

As you can see, there’s plenty of capacity on the board. A total of 5 330uF 35V low ESR capacitors are placed in parallel in order to smooth out the PWMs inherent current ripple.

Software

So now we have a device with 2 rotary encoders and 4 outputs but it won’t do anything without software. There’s absolutely nothing hard-wired between the encoders and the outputs so we can program this device to behave in any way we like. That’s what makes it so flexible.

I have so far implemented two functions. The first is aimed at RGB LEDs and behaves exactly like my RGB dimmer. One encoder controls the brightness, pressing its button turns the outputs on and off. The other encoder controls the color, pressing its button toggles between white and color. The three outputs are 120 degrees out-of-phase which presents a more steady load to the power supply.

The second function is aimed at plain white LEDs. There are two pairs of outputs with output 1 & 2 forming a group and 3 & 4 the other. Each pair is controlled by one encoder. Turn it to control the brightness and press its button to turn the respective output pair on and off. The two outputs of any group are 180 degrees out-of-phase to smoothen the load. And since there is a 4th output it is easy to implement a case where there is an independent white channel.

With both functions, the entire device turns off after a pre-defined period of time (currently set at 3000ms) with all outputs off in order to save power. Before turning its own power supply off and hence losing all its data in RAM, the necessary parameters are saved to EEPROM. So the device remembers its last state and will power up the with the same (brightness, color and so on) settings it powered off with.

The switching frequency is 31.25kHz which is high enough to be entirely inaudible and the 10bit resolution gives you 1023 levels to finely control the brightness down to very low levels.

All the settings reside in a file named config.h. That is where you define the function you want the device to perform. The number of brightness levels and their respective values can simply be parameterized there. The same is true for the colors. You can also set the RGB values for neutral white. The seemingly obvious choice of 1023/1023/1023 often does not result in a pleasent white. For my LEDs I had to substantially reduce the green content but this, of course, depends on your particular choice of LEDs.

I currently have 3 devices productively deployed and they perform very nicely. Also, adding new functions is easy since all the heavy lifting like has already been done. It takes somethign like 100 lines of relatively simple code to implement a new function. No need to get involved with any registers and the like. So if you have any experience in C you should be totally fine programming this thing.

Visit github for code and Eagle files

Both the eagle files (including Gerbers) and code are on github:

Also want one?

I have some boards left and can make one for you, too. Fully built, tested and programmed to your needs. Cost is USD 65 payable via PayPal, including worldwide shipping. Simply contact me using this form.

MPPT Solar Charger Testing

20160927_solarcharger_036

In a previous post I have presented a design for an MPPT Solar Charger. In the mean time I have built a prototype and also wrote some software for it. So today I’ll go through my findings of what works well and what needs to be improved. And yes, there are some flaws in the design…

The software is far from final but with the notable exception of USB all the basic functionality has been implemented.

Power Supply

20160904_solarcharger_002

One of my main goals with this design is to archieve very low standby current, somewhere in the tens of microamps. The basis for this is a low-power buck on the basis of a Texas TPS62120 where the microcontroller can switch the output voltage between 2.2 and 3.3 volts nominally. This works as intended. With no load and the output voltage low, the supply consumes 12.9 microamps at 12V input voltage. With the high output voltage the idle current goes up to 14.3uA. Quite a bit of that current is due to the voltage divider that sets the output voltage. The regulator itself consumes about 9uA in both cases.

Microcontroller

20160928_solarcharger_045

The PIC18F26J50 starts up using the primary oscillator’s 8MHz crystal with the internal PLL disabled. It can then switch to 48MHz operation by enabling the PLL or to the secondary oscillator running at 32.768kHz. The latter is always running since it also serves as the clock source to the real-time clock and calender (RTCC). Switching between clock sources as well as the RTCC have been implemented in software and work fine.

I2C Multiplexer and Port Expander

20160928_solarcharger_046

The microcontroller doesn’t have enough GPIO pins so a I2C port expander (Microchip MCP23008) is used to give us another 8 pins. The display is connected via I2C as well but since the display is entirely powered off when not in use, the display cannot be on the same bus. Otherwise it will pull the SCL and SDA lines low and block the bus. The NXP PCA9546 multiplexer takes care of that. Both devices, the mux as well as the port expander work as they should.

Voltage Reference, Temperature Sensors and Fan

20160904_solarcharger_004

There is a total of 3 temperature sensors, one on the board and 2 external ones. The temperature is measured by the PIC directly so it has a 2.5V voltage reference in order to get meaningful results. At room temperature all three temperature sensors deliver very similar results, typically within a few tenth of a degree. Better than expected. The fan output can also be enabled if the on-board temperature gets too high.

Voltage and Current Measurements

20160928_solarcharger_047

The more important measuements, namely the input and output voltages and currents are performed by a MCP3424 4-channel 18-bit ADC. I was already familiar with that type so I quickly got it to work. In this application I don’t use its internal PGA (programmable gain amplifier) or rather I leave the gain at 1. All the measurements are done with 14bit accuracy which is reasonably fast (23ms worst case) and sufficient here.

User Interface

20160904_solarcharger_006

The debouncing of the rotary encoder works ok but I’ll tweak the resistor and capacitor values a bit when I get time. The push button is uncritical but there is a bit too much debouncing for the rotary encoder itself making it miss some very fast turns. But it already performs reasonably well as it is.

The display module is the first real flaw in my design. It has 5 wire connections: GND, VCC, SDA, SCL and Backlight. The idea was to turn the display off by simply cutting off VCC when the display is not needed. When in use, the brightness of the backlight is then controlled by the Backlight PWM signal.

20160905_solarcharger_015

Since the display needs quite a few supporting components (mainly 1uF capacitors) and has no mounting holes I made a little one-sided PCB for it. When I first tried it nothing worked. A ground connection was missing and I didn’t notice that in Eagle because in Eagle it was a double-sided board. That was easily fixed by a short piece of blank wire soldered in place. So far so good.

Unfortunately the display (a Midas MCCOG42005A6W-BNMLWI) still didn’t work. Besides the data sheet being a nightmare it needs to be reset after having powered up. So you need to power it up, wait for a while and then do a reset by pulling its reset pin low. So just pulling the reset pin high with a resistor like I have done won’t work. My solution for now was to connect the backlight signal to the reset pin. So I can now use the display but the backlight brightness is permanently  at it’s maximum.

20160905_solarcharger_017

I already have a new and hopefully better version of this display unit in the making and there will be a separate post on that. My idea is to have a rather universal module that I can use in other projects as well.

USB Charging

20160928_solarcharger_049

The USB charging module works reasonably well. When pulling the full rated current of 2A it gets rather warm but doesn’t overheat. I was able to pull 2.5 amps for a prolonged period of time without any issues. I only had a Samsung A5 to try but at least that phone charged perfectly fast pulling around 1A of current. With that load the module only gets slightly warm.

20160927_solarcharger_038

Turning the USB charger on and off in software also works as planned. This can now even be done via the user interface – see above.

Power Outputs

20160928_solarcharger_053

The 4 power outputs can be controlled in software. In order to save power, the mosfet drivers can be powered off if none of the outputs is on . All that is already implemented in software and the outputs can be turned on and off individually via the user interface.

20160927_solarcharger_037

I plan to implement a low-frequency (say, 100Hz) PWM functionality for these outputs in order to e.g. control some LED lighting but that has not been done yet.

EEPROM

20160927_solarcharger_042

I haven’t implemented any data logging functionality yet but I have written a few library functions for the EEPROM. When the date and time is set via the user interface those values are saved to EEPROM and restored after a reset. Reading from and writing to the EEPROM therefore works.

20160927_solarcharger_041

Solar Charger

Yes, I’ve left the main thing for last. Don’t know why.

20160928_solarcharger_051

When I first assembled the board I noticed that I had ordered the wrong mosfet driver – a MIC4605-2 instead of a MIC4605-1. They are near-identical except the fact that the -1 has two independant inputs while the -2only has one PWM input plus an enable signal. That also works but doesn’t give us the option to run the converter in asynchronous mode. So I’ve unsoldered the chip again and replaced it with the MIC4605-1 that I had in mind when I designed this thing.

20160928_solarcharger_050

As you can see on the photos above, I’m now using a 22uH coil, not a 68uH coil as shown in the schematic. The reason for that is that I’m using a relatively high switching frequency of 48MHz / 256 or 187.5kHz. That high switching frequency enables me to use a lower value inductor which massively increases its current rating while pyhsically being the same size. Since the inductor was the limiting element in this design before this significantly increases the power rating of this solar charger. The previous version was (very conservatively) rated at 30 watts only. With the new 22uH inductor this very similar design can handle something like 75 watts. I need a more powerful power supply to do some serious testing but at 35 watts it’s getting slightly warm at the most. I’ve only done some quick and dirty testing but efficiency at 35 watts is around 97%. That means we are only losing about 1 watt which is the reason the charger barely gets warm.

20160912_solarcharger_026

There will likely be another post focussing only on the charger itself so I won’t go into more details here. The code regarding the buck is extremely basic and potentially dangerous at this point. I’ve killed the bottom mosfet twice due to the not very graceful way the buck turns off. If it turns off while the bottom fet is on, that fet will stay on, effectively shorting the battery to ground. At least that’s my explanation at the moment.

20160927_solarcharger_033

Oh yes, there’s another issue with the buck as well. With the battery at its output there will always be the battery voltage minus a diode drop at its input where the panel is connected. So when there is no sun, the battery is powering the panel. I’ve tried that with a small 30W panel and the panel draws 8mA at 12 volts which several magnitudes more than we are willing to use when the charger is sitting idle. So the next version will have to disconnect the panel when the charger is off. And we will also need to disconnect the voltage divider at the charger’s input when we’re not measuring the voltage, just like we’re doing at the battery.

Summary

There are a lot of features on this board and getting them all to work properly requires quite a bit of work. But most of the heavy lifting has been done so I can now focus on improving the software.

20160912_solarcharger_030

First and foremost I need to work on the way the buck is controlled. First there needs to be a strict and safe procedure how this thing is turned on and off. I’m confident that there won’t be any blown-up mosfets once that’s done. Then I also need to improve the algorithm of how the maximum point of power is tracked. And I also want to implement asynchronous operation at low loads in order to improve efficiency. I’ll spend some time on all these issues next, looking at the signals on a scope and trying to improve things.

But all-in-all I’m quite happy with how how this design has performed so far. Yes, there are some issues but nothing that can’t be fixed with relative ease.

For those of you interested, the code can be found under downloads on the overview page. In my next post we will take a closer look at the display unit / user interface.

Ultrasonic Anemometer Part 28: New hardware tested

20160907_standaloneanemometer_024

I last time proudly presented the new RevB board and got a lot of feedback from people who want one, too. As mentioned I have all the components here to ship up to 10 kits but I was reluctant to send anything until I had the chance to do some hardware testing. Not much had changed since the last revision but I don’t like taking chances on things like this.

20160907_standaloneanemometer_029

In the mean time I managed to do some rudimentary testing and now feel confident to take orders. These tests concern the hardware only. What I said last time about the state of the software still applies. But let me tell you what I’ve been able to test so far.

rxtx_overview

Tests performed so far

  • The PIC32 can be programmed from a PICKit3 via the ICSP header without any issues.
  • Power consumption is as expected. Like the previous version it draws 45mA@12V (programmed) and the other two rails come up with +3.310 and -3.279V, respectively. Also as expected. Regulator stays cool.
  • With the PIC controlling the AXIS, DIRECTION and SIGNAL pins, the transducers receive the 12V signal from the mosfet drivers. HOWEVER: the signals AXIS and DIRECTION are incorrectly labeled both in Eagle as well as on the silk screen. Electrically everything is fine but the names have been confused.
  • The signal from the transducers is properly received (Rec pin on the board) and amplified by a factor of 11 by the first stage of the amplifier (S1 pin on the board).
  • The PIC is able to control the digipot over the internal I2C bus and the second amplifier stage also performs as expected.
  • The zero-crossing detector (ZCD) works.
  • The input to the PIC’s ADC (ADC+ and ADC-) look fine, too. HOWEVER: the labeling on the silk screen is wrong. Eagle is correct, it’s just the silk screen. Plus should be minus and vice-versa. Again, electrically everything is fine.
  • The PIC can communicate (as a slave) with an Arduino UNO connected to the external I2C bus.
  • Communication over USB to a YAT-terminal under Win 7 works.

rxtx_north

rx_closeup

The following has not been tested so far

  • For my tests I still used the transducers already used previously. I believe the ones I ordered last week are of the same type but I haven’t tested them.
  • EEPROM. I haven’t tried the newly added memory yet. I have confirmed that it has power and is connected to the same bus as the digipot so I have no reasons to assume there are issues with it. But testing it would require some software first.
  • The external SPI bus has never been tested, neither on the Rev A board nor with the new one. I don’t expect any problems but I haven’t done any testing so far.

20160907_standaloneanemometer_028

Is there anything important that I forgot to mention? In that case just ask.  A lot still needs to be done but at this point I’m confident that the board has no major flaws and performs much like the prototype.  Want to give it a try? I have some kits left for you.

i2c1_arduino

Continue here to the next post of this series.

Ultrasonic Anemometer Part 25: I2C Interfacing and more

20160706_StandaloneAnemometer_023

It’s been a long six weeks since my last post but that doesn’t mean that I haven’t done anything since. Among other things, I wrote some code to get the I2C interface working and hooked the anemometer up to an Arduino Uno with an LCD display attached. Apart from demonstrating the I2C interface this also nice for testing. For the first time I can see what this thing is measuring in real time without hooking it up to a PC over USB.

20160710_StandaloneAnemometer_025

I2C Interfacing

But let’s look at the setup in some more detail. The PIC has a total of two I2C interfaces and I’ve made both of them accessible via the 100mil headers along the edges of the board. One of them is primarily intended for internal purposes like controlling the gain via the I2C digipot. The other one can then be used to interface to some external logic without having to worry about any internal communication. This external I2C interface also comes with 5V compatible pins which means we can interface to 5V devices like an Arduino without any further logic level translation. All we need is a pair of pull-up resistors pulling the SDA and SCL lines up to 5 volts. The Arduino’s Atmega328 already has built-in (weak) pull-up resistors so that’s not a problem. I didn’t think of interfacing to a 5V device when I designed the board and pulled the I2C signals to the anemometer’s 3.3V supply. So for proper 5V operation I’d have to unsolder the two 10k resistors. Luckily, 3.3 volts is enough to almost certainly be recognized as a logic high by the Arduino so the setup works anyway. But I will think about how to improve this in the next version. I might add a diode to allow the lines to be pulled higher than 3.3 volts.

The I2C interface can be configured to act as a master or as a slave device. For now I’ve only implemented slave mode so the wind meter behaves just like a I2C temperature sensor or external ADC. The Arduino acts as a master and asks the slave for its latest measurement every 250ms. The anemometer then returns 8 bytes of data consisting of 2 status bytes, north-south wind speed, east-west wind speed (both in mm/s as signed 16-bit integers) and temperature (0.01 degrees centigrade as signed 16-bit integer). It’s also possible to send data to the anemometer. That data is then saved to a buffer is otherwise ignored.  In a future version of the software one might use this functionality to set the data format to wind speed and wind direction or to change the temperature unit to kelvin or fahrenheit.

20160710_StandaloneAnemometer_027

It would not be difficult to implement master mode as well but so far I haven’t done it yet. A lot of code could be copied from the module communicating with the digipot where the PIC acts as a master. The anemometer could then push data to an external device whenever a new measurement becomes available. Definitely something I’d like to implement at some point but no priority right now.

Bug fixes

I’ve found (and fixed) a number of bugs while testing. Among other things, the axis and direction signals were not always properly set and so the measurements did not always correspond to the direction they should. So take with a grain of salt some of the test results reported earlier. Some of them were almost a bit too good to be true and this bug might have been the cause. I suspect I might have compared two successive measurements in the same direction when I actually wanted to compare measurements taken in opposite directions. But I’ve fixed the code and I’m confident that now all the directions are set and reported correctly.

Individual filter kernels

EqualAmplitudes

As can easily be seen from the scope screenshots above, the shape of the received signal varies quite a bit from transducer to transducer. Note that the amplifier gain is dynamically adjusted to make sure the peak amplitude is the same for all of them but the shape still differs quite substantially. So the kernel for the matched filter has to be some compromise to suit them all. I have now modified the software to use four individual kernels, one for each direction. This gives us the flexibility to calibrate the kernel to each transducer and so get more reliable results for the absolute phase.

Revised board

20160710_StandaloneAnemometer_026

My main priority at the moment is to complete the revised version of the board and to order a small series of boards. Until recently I never ordered a board from a professional board house so there are quite a few things for me to learn. For the first time I have to worry about silk screen, for example. Or solder mask. On the other hand, a board house can do a lot of things I can’t. Plated-through holes for example. Or smaller vias. Or place vias under an IC. This means a lot more flexibility in my layout that I first have to get used to. But I’m making progress. I got a simple design of mine produced by dirtypcbs.com and got a batch of very usable boards. More on that in a future post.

Wind tunnel

If you’ve been following this project for a long time already you might remember my simplistic wind tunnel made of a 120mm brushless fan and a cardboard tube. I got a number of suggestions from you guys on how to build something better than that and I also found some useful material online. So I’ve started to build a much improved wind tunnel that will hopefully allow me to perform more meaningful tests. That’s also for one or more future posts.

20160706_StandaloneAnemometer_021

Software ideas

I’ve also played around with some software ideas that I believe to have potential. One is dynamically adjusting the frequency. I’m now only working at the transducer’s nominal frequency of 40kHz. But the individual transducer’s resonance frequency might be somewhat different and might change with temperature or age. So I might try to adjust the frequency dynamically using some perturbation and observation algorithm.

I’m also thinking about measuring at two slightly different frequencies (say, 39.5kHz and 40.5kHz) and using the two phase shifts to figure out the absolute time-of-flight. I’ve given it a try and was not very successful but I haven’t given up on that idea yet.

So that’s it for now. The code for the Ultrasonic Anemometer as well as the Arduino are available for download. See the overview page for the respective links.

Ultrasonic Anemometer Part 24: New Microcontroller and Software Controlled Gain

It’s been almost three weeks since my last post and some further progress has been made. I’ve upgraded the microcontroller and can now control the gain of the second amplifier stage in software. But let’s look at the changes in some more detail.

20160625_AnemometerDriver_008

New microcontroller: PIC32MX250

I mentioned last time that I was running out of code space, i.e. flash memory on the PIC32MC220. That particular model has only 32k of flash and I’m using the free version of the XC32 compiler. That free version only performs limited amounts of optimization and therefore produces rather large and slow code compared to the standard and professional version. But the other two are rather costly (around USD 500 and 1000, respectively) and are not really an option here.  And at least so far I’ve always had all the speed I needed so the only issue was flash memory.

So the straight forward solution was to upgrade the microcontroller to an otherwise identical model with more memory. The 250 I’m using now has four times more of both flash (now 128k) and ram (now 32k). I unsoldered the old chip using a hot air gun and soldered in a PIC32MX250 in its place. Now we have all the flash we need to continue our journey.

20160625_AnemometerDriver_005

Getting I2C to work

My design uses a dual op amp for the necessary amplification of the received signal. The first stage is ground-referenced and uses a simple resistive divider to set the gain (currently set at 11).

The second stage is biased to 1.65V (i.e. half way between ground and 3.3 volts) and has its gain controlled by a I2C digipot. The idea is to have the PIC control the digipot so it can adjust the gain as needed to compensate for any effect that might change the amplitude of the received signal.

So in order to control our digipot we first need to get the I2C interface working on the PIC. There are two (identical) I2C peripherals on the PIC32MX2xx and this design uses one of them (#2) exclusively to communicate to the digipot. The other one (#1) is then available to interface to the outside world.

I’ve written a set of simple functions to use the I2C interface. So far I’ve only implemented  master transmit mode since that’s the only thing we need here.

  • void app_i2c_internal_init(void);
  • bool app_i2c_internal_write(uint8_t address, uint8_t *data, uint8_t length);
  • void app_i2c_internal_writeDigipot(uint8_t value);

The functions are entirely non-blocking so they can be called from within the interrupt service routines that do the measurement.

Fixing a design bug

Unfortunately, I made a mistake in the schematic when I referenced the feedback loop of the second op amp stage to ground instead of the mentioned 1.65 volts. Now let’s look at what that did to the signal. First, below is the signal with the digipot at 0 (of 256). The gain is set to one and all is well.

AmpError_Pot0

But at a setting of 64, some clipping starts to occur as shown below.

AmpError_Pot64

With the gain turned up to 4 with a digipot setting of 192 things get really uggly with a completely unrecognizable output signal.

AmpError_Pot192

I was extremely lucky that the correct signal was available right next to the pin where I needed it so all I had to do was to cut the ground connection with a carving knife and to connect the correct signal using a tiny bit of wire.  The change is hardly visible on the photo below. Can you spot it? It’s almost at the center of the photo at pin 5 (bottom right) of the small 8-pin IC. It now connects to the 10k resistor at the bottom instead of the ground plane on its right.

20160626_AnemometerDriver_009

Controlling the gain in software

With that error fixed we can now set the gain as we please. Here some examples. Yellow is the (unamplified) input signal whereas green is the output of the (fixed) first amplifier stage.  The purple signal is calculated as the difference between the DAC+ and DAC- signals. Those two signals is what we feed into the PIC to be measured.

With the gain at 1 (digipot at 0) we get a about 2.6 volts peak-peak. A bit little but sufficient.

Amplifier_Pot0

This is probably about what we want. Digipot at 50 resulting in a peak-peak amplitude of a bit above 3 volts.

Amplifier_Pot50

Needless to say that we can jerk the gain up far more than that if we want.  Below is an example where a gain of 4 results in a seriously clipped signal.

Amplifier_Pot192

Now let’s look a a situation where such a high gain might actually be useful. In the example below I’ve lowered the input voltage to only 5 volts. As a result the received signal is only 90mV in amplitude instead of the 220mV seen above. That’s easily compensated with a bit of help from our digipot. With a setting of 170 we get a nice, clean 3 volt output signal.

Amplifier_Vin5_Pot170

Calculating the necessary gain

For the examples above I’ve explicitly set the gain in the code. But what we really want is to have the software calculate and set the necessary gain automatically.

So I’ve implemented a simple algorithm to do so. I set some target value for the peak-to-peak amplitude of the signal measured by the DAC. Knowing the amplitude and digipot setting of the last measurement I calculate the optimal gain and digipot setting for the next measurement.

AmplitudesGain1

Above is the signal without this automatic gain setting in place (gain=1). As you can see, the peak-to-peak amplitudes vary quite a bit between transducer pairs. So the gain calculations, too, work on a transducer pair basis. Each direction gets its own setting to compensate for different transducer sensitivities.

Below is a screenshot of the result. Notice how now all transducer pairs have identical (and somewhat larger) amplitudes.

EqualAmplitudes

That’s it for today. Click here for my next post.

Ultrasonic Anemometer Part 22: USB up and running

20160514_StandaloneAnemometer_047

Last time I showed you the nice new hardware of the new standalone ultrasonic anemometer. But at that time I had hardly any software written for it so I couldn’t do much with its 32 bit microcontroller. So the last two or three weeks I spend lots of time writing code that I’d like to share with you today.

20160428_StandaloneAnemometer_039

As I mentioned last time I worried most about getting the USB working properly. All the bit-fiddling with timers, PWM modules, input capture modules and the like can be time consuming and at time even frustrating. But I have all the confidence that I finally get what I aimed for. It might take a few nights digging through data sheets but in the end it will almost definitely work.

Now with USB I don’t quite have that level of confidence. The USB specification is quite overwhelming and there are almost countless registers to properly set and USB descriptors to specify. Without some sample code I’m pretty much lost I must admit.

Outdated Application Notes

So I was happy to see that Microchip has published a number of application notes and accompanying software. A handful of .h and .c files that you can include in your project, change some settings to suit your particular application and you’re ready to go. At least that’s what I thought.

20160514_StandaloneAnemometer_048

All those application notes were published around 2008 and the code they are referring to is nowhere to be found nowadays. Aparently, Microchip has been quite pushy trying to get their PIC32 customers migrate to their new library or rather framework called Harmony. MPLAB no longer even includes the the PLIB peripheral library everyone has been using for decades. Microchip has depreciated it and while you can still download it they make very clear that Harmony is the library of the future.

On the road with MPLAB Harmony

So faced with few other alternatives I turned to the aforementioned Harmony library. It’s many hundred megabytes to download and takes up almost two gigabytes of disk space. It integrates nicely into MPLAB X and so I created a first project. You can graphically configure the clock and pin settings so I did that. Clicked on ‘create code’ and was nothing less than shocked by the code I got.  Around a dozend source files scattered around in a dozend deeply nested folders and subfolders. And that was not yet it. Those files referenced dozends more files that came as part of harmony. It took me quite a while to just more or less figure out what the project was doing. And it didn’t do anything yet except setting some clock and port settings. Just a nightmare.

20160514_StandaloneAnemometer_045

But I felt I had few other options so I continued with harmony anyway. And after a few hours I had an almost working USB device. It enumerated just fine but I couldn’t send any data from or to it. It took me more than a week to finally get it working. In the end it was just a single character: a 1 instead of a 2 in one of the configuration files. But until then I had spent a lot of time with that harmony code and was forced to read through a lot of its documentation which is worth thousands uppon thousands of pages of PDFs.

So USB was finally working and I had acquired some rudimentary understanding of MPLAB Harmony. I still hated the whole framework but I thought that I now understand it well enough to change the code to suit my taste. So I spent another few nights trying to do that until it dawned on me that this is leading nowhere. Fortunately, by that time I had read and learned some more about Harmony and was willing to give it another try working with it as opposed to against it. So for the last week or so I was doing that.

And while I still don’t love everyting about it I now feel comfortable working with that library. I’ve tried to follow its conventions and recommendations even where they didn’t make too much sense to me. I think this will make it much easier for others to work with my code and chances are that the conventions and recommendations will start to make more sense as I get more familiar with the framework. And its nice to know that I can integrate another module or migrate to another microcontroller without having to re-invent everything.

20160428_StandaloneAnemometer_037

That was a long introduction but after all that pain the last few weeks I just had to write that down. Now to business.

USB

The anemometer inplements the USB HID (human interface device) class. While mainly aimed at devices such as mice and keyboards, this USB device sees a lot of use in applications that have nothing to do with human interaction. You can transfer up to 64 kbytes of data (64 bytes every millisecond) in each direction with guaranteed latency and that’s plenty for many applications. That data can be anything and in any format you like. And the good thing is that you don’t need to write your own drivers. You can free-ride on the device drivers that came with the operating system just like you don’t need to install a driver when you attach a new keyboard to your computer.

I’ve written a bit of code on top of the Harmony library to provide the main application with a simple to use interface. It nicely encapsulates the the USB logic and data and adds a bit of buffering functionality on top of that. It’s just two files: app_usb.h and app_usb.c in the app_usb subfolder. You can basically include them in your project and they handle all the USB stuff for you.

Once initialized, the necessary code runns inside an interrupt service routine (ISR) so the main application has nothing to worry about. All the USB data including the data buffers are private to the app_usb.c file. The app_usb.h defines just 8 simple, non-blocking functions:

  • void app_usb_init(void);
  • bool app_usb_isReady(void);
  • uint8_t* app_usb_getReceiveBuffer(void);
  • uint8_t app_usb_getReceiveBufferCount(void);
  • uint8_t* app_usb_getTransmitBuffer(void);
  • uint8_t app_usb_getTransmitBufferCount(void);
  • void app_usb_freeReceiveBuffer(void);
  • void app_usb_sendTransmitBuffer(void);

At system initialization you call app_usb_init(). But you can’t expect to have an USB connection. You need to check app_usb_isReady() every time. You never know if there is a USB cable plugged in and even if you had a connection that cable might be unplugged at any time. The module handles all that hot plugging/unplugging gracefully.

20160428_StandaloneAnemometer_038

The module implements a circular buffer for both received packages (aka frames) and packages to be sent. Each package is 64 bytes in size and the ring buffers can be set at compile time but must be a power of 2. Currently the receive buffer consists of 4 frames and the transmit buffer of 8 frames.

The app_usb_getReceiveBufferCount() informs the caller how many new USB frames have been received if any. app_usb_getReceiveBuffer() then returns a handle to the first received frame. FIFO – First In First Out. Once the frame is no longer needed the application calls app_usb_freeReceiveBuffer() and the buffer can be re-used.

Sending data works similarly simple. app_usb_getTransmitBufferCount() returns the number of transmit buffers currently in use. If this  number is smaller than then number of buffers then more data transmissions can be scheduled. Get a handle to then next buffer by calling app_usb_getTransmitBuffer(), write the data to be sent to the buffer and then call app_usb_sendTransmitBuffer().

Taking measurements

This way the main application can focus on more interesting tasks such as measuring wind speed and direction. The first task for doing so is sending some pulses.

SendReceiveOverview

If you’ve alredy followed this project for a while you are probably familiar with the kind of screenshot above. Bursts of a PWM signal at 40kHz (SIGNAL, red) are sent trough ultrasonic transducers. Note that the signal is now active-low (i.e. inverted) since the mosfet drivers used to drive the transducers are themselfs inverting.

As before, the DIRECTION  and AXIS signal determine which transducer is transmitting and receving. The SCLK and MOSI signals are just used for debugging purposes for now. They indicate when an ISR is running which helps a lot since in this example ALL the code is running inside an ISR.

TimeZero

As you can see above, the AXIS and DIRECTION signals are set a few microseconds before we start sending pulses. The first edge of the burst occurs when the 32 bit-timer (consisting of the 16-bit timers TMR2 and TMR3) is cleared. This is the point in time all our measurements are referenced to. The timer runs at the full CPU clock of 48Mhz so the resolution is about 20.8 nanoseconds.

SendReceivePWM

Output Compare module 2 (OC2) handles the PWM pulses. Currently each burst consists of 12 pulses. At 48MHz a full wave equals 1200 clock cycles as opposed to 400 on the Arduino previously used. Note that the frequency of the pulses is precisely 40kHz as expected and that very little time is spend in ISRs despite the unoptimized C code.

SendReceiveCloseUpWithComments

The timer overflows precisely 512 times per second so each measurement takes a little less than 2 milliseconds. Output compare module 1 (OC1) can be used to generate an interrupt at any time during that interval. Currently it does three things: It takes care of the AXIS and DIRECTION signals which are set just shortly before the timer overflows. It also triggers the measurements of the zero-crossings and cancels them if they don’t complete withing reasonable time.

ZCD_Capture

The input capture module 4 (IC4) captures the zero-crossings of the received and amplified signal. The board contains a high speed comparator to detect these events so the microcontroller only needs to measure the precise time whn they occur. The IC4 module has an internal buffer so we don’t need to generate an interrupt after every capture. I’ve currently set things up so that an interrupt occurs after 4 values have been captured up to a total of 32 measurements.

Commicating the results over USB

In order to find the wind speed and direction we need to somehow identify the peak in the received signal which is where the ADC comes in. But I think this is enough for now and I instead show you how the measurements taken so far can be sent to a PC via USB.

The board doesn’t have any display or anything to communicate with a human. There’s not even a status LED we could blink. That would have been nice but there are just not enough I/O pins unfortunately. So connecting the board to a PC via USB is a straight-forward way of communicating with this device.  Actually, USB will be the main testing and debugging tool during development. The in-circuit debugger isn’t very useful in this application since the measurements have to happen in real time.  Setting breakpoints will just mess things up.That’s why I insisted to get USB working first.

I’ve downloaded a simple terminal called YAT (yet another termial) that allows me to easily talk to the anemometer board. The anemometer looks at the first character in any message sent from the host and then decides what to do. So far I’ve implemented:

  • ‘T’: Return the current value of the 32-bit timer
  • ‘Z’: Return axis (0/1), direction(0/1), measurement count (0-31) values as well as the results of the first 9 zero-crossing measurements
  • Anything else: Echo back the received string

Here’s what my chat with the Standalone Ultrasonic Anemomete looked like.

YAT_Capture

Of course, the measurement is far from complete at this stage but I think this is a nice foundation to build uppon. The code is quite clean for this early stage of development and being able to communicate with the device in real-time over USB is really a great advantage.

The software can be downloaded on the project over view page and as always I appreciate any feedback.

The next post on this project can be found here.

Ultrasonic Anemometer Part 21: Standalone Anemometer Hardware

Last time I went through the design of my new standalone anemometer. Now it’s time to build this thing and see if it works as planned.

20160428_StandaloneAnemometer_034

After I fried a couple of chips on my driver circuit testing board due to a wrong chip in the power supply I was a bit more careful this time and built up the board step by step.

20160426_StandaloneAnemometer_016

Only after I confirmed that the power supply was ok I dared to solder some more.

20160426_StandaloneAnemometer_019

The next step was to add the PIC32 with the crystal, the programming header and all the caps they need. This is a chip family that I’ve never used before so I wanted to first see if I can program it. All went well and I managed to get it to run on the crystal’s 8MHz boosted up to 40MHz by an internal PLL. So I was ready for the rest.

20160428_StandaloneAnemometer_031

I wrote some very basic software and confirmed that at least the basics were working ok. I was able to send and receive pulses, the pulses got amplified, the zero-crossing detector worked and so forth.

20160428_StandaloneAnemometer_024

As mentioned, I’m entirely new to the PIC32 microcontroller series. There are a lot of similarities to the PIC16 and PIC18 series that I’m quite familiar with but still it’s always a challenge to work with a new family of chips and the tools that come with it. I took me the better part of an afternoon to master the vectored interrupts with the different priority levels and so on.

20160428_StandaloneAnemometer_040
Driver circuit (front) and standalone anemometer (back) side by side.

By the way, with this project I’m using the free MPLAB X IDE with the also free XC32 C compiler from Microchip. So anyone is able to write, modify or compile code for this thing with free software. At least at the moment you need a programmer to actually burn the chip. But the PICkit3 only costs around 50 dollars and my idea is to write a USB bootloader so that any user can modify the software of a pre-programmed board.

20160514_StandaloneAnemometer_050

So now comes what I think might be the hardest part: Getting the USB to work. I’ve spent quite a few hours so far but haven’t managed to get it working properly yet. If anyone has experience with this kind of software development – Let me know, any help is highly appreciated.

It now works: Click here to view it.

Ultrasonic Anemometer Part 20: Standalone Anemometer Design

Last time I outlined my reasons to ‘go digital’ by adding a powerful on-board microcontroller and designing a standalone wind meter.

20160426_StandaloneAnemometer_001

In the weeks that followed that decision I tried to find a suitable microcontroller and to design a prototype. Today I’ll show you the result of that work.

20160426_StandaloneAnemometer_003

I looked at various series of microcontrollers from different manufacturers and finally decided to go for the Microchip PIC32 series. It offers everything I could possibly ask for: 32 bit architecture, inexpensive, vectored interrupts, integer division, any interface you want (depending on the model of course) , available in large, low pin count, hobbyist friendly packages and so on.

20160426_StandaloneAnemometer_011

As you can see above, the model chosen for my prototype is a PIC32MX220. This is low to mid-end representative of this series but even so the specs are quite impressive. CPU clock up to 50MHz, one instruction per clock cycle, full-speed USB 2.0, 32kB flash, 8kB RAM and all of that in a SOIC28 package at a price of CHF 3.58 in single quantities.

20160426_StandaloneAnemometer_005

After having chosen a chip the next task was to come up with an actual design. I took my anemometer driver design and tried to integrated the new PIC32. That driver circuit had performed extraordinary well so I changed very little. I left away the RELEASE signal since my tests had shown it to be unnecessary. I also replaced the LM5111-1M mosfet drivers by LM5111-2M. The difference is that the 2M is inverting while the 1M is not. The reason for changing this is because the 2M is available at a significantly lower price of CHF 1.35 vs CHF 2.25. Not a big deal if you just build a single prototype but I thought it might be smart to change this anyway. This also required some resistors to be changed from pull-downs to pull-ups. Except these details everything stayed the same with the drive circuit.

20160426_StandaloneAnemometer_012

I also had to re-design the power supply since the PIC needs a 3.3 volt rail as opposed to 5 volts in the driver test circuit. Since I had to re-design it anyway I also downsized the power supply somewhat. I’ve otherwise resisted all temptations to use smaller components but the power supply was just a bit too big with the two  SOIC8 chips and four size C tantalum caps.

The prototype now uses an MCP1755 linear 3.3V regulator in a SOT23-5 package with a 33uF size B tantalum cap at its input and a 10uF 0805 size ceramic cap at the output. A TCM829  (also in a SOT23-5 package) and two more 10uF caps produce the -3.3 volts output. So there is a total of three supply rails: +12V, +3.3V and -3.3V.

20160426_StandaloneAnemometer_006

A major challenge was to make do with the very limited number of I/O pins on the PIC. 28 pins seem like a lot for the task at hand but plenty of them are already used for things like supply voltages and the like.

In the end I managed to still get three independent interfaces to the outside world: USB 2.0, I2C and SPI. All these interfaces as well as just about any other signal of interest is easily accessible from one of the numerous 100mil headers along the edges of the board.

20160426_StandaloneAnemometer_007

The amplifier still uses a LMC6482 dual op amp , now running on a+/- 3.3 volt supply. The first stage amplifies the ground-referenced input signal by a fixed factor (currently 11 but this might change). The output signal is then biased to 1.65 volts and amplified once again. This time the gain can be adjusted digitally via a MCP4561 I2C digipot.

20160426_StandaloneAnemometer_008

Before I forget: The PIC gets its system clock from a 8MHz crystal. That might seem low but there are two (variable)  PLLs inside the PIC that (together with a number of pre- and post-scalers) let us produce the 48Mhz signal needed for USB as well as a reasonable clock speed to run the CPU and peripheral bus on (probably also 48MHz but we’ll see).

20160426_StandaloneAnemometer_013

The board layout proved to be a bit tricky because there isn’t that much space on the board and I had quite clear ideas where I wanted certain headers to be. So I was more than happy when all the traces were finally laid out.

As you can see, the PCB is already milled and the vias soldered. I can’t wait to build this thing up and start to do some programming. That will be the topic of my next post.

20160426_StandaloneAnemometer_014

As always, a zip file with the eagle files and PDFs of the schematic and board layout can be found on the overivew page.

And here‘s the finished board.

Temperature Controlled Fan

20160409_FanController_020

I’m currently mainly working on my new anemometer design but once in a while I get distracted. For example when my Keysight E3645A lab power supply was making so much noise that I could hardly concentrate. That’s when the idea of this fan controller was born.

20160403_FanController_012

Of course, the best temperature controlled fan in the world doesn’t help if you really need the cooling the fan is providing. But very often a small fraction of the cooling would do just fine most of the time. In my case the supply does control the speed of the fan. But it doesn’t seem to measure the temperature at all but seems to calculate the necessary cooling in a worst-case condition. An for a supply that may be rack-mounted together with lots of other heat dissipating gear the worst-case might be quite demanding. But my supply just sits on a shelf at, say, 22 degrees ambiant. And most of the time I’m hardly pulling any current. When working with microcontroller designs it’s rare for me to pull more than a few tens of milliamps. So little cooling is needed most of the time. But the E3645A (this one here does a better job) ran its fan at crazy speeds while the case still had this cold metallic feel to it.  So we can definitely do better.

20160314_FanController_017

So the first step was to open the supply and to see what kind of fan it uses and how it is controlled. After beaking some seals and opening the case I found a 60x60x25mm 12V fan of Chinese origin. I also found out that the supply uses linear control. So there’s no PWM or anything but the supply voltage just varies in (I think) four steps from 7.4 to 12 volts. Most surprisingly, this voltage is not ground-referenced but symmetric around ground, i.e. plus/minus 6 volts.

20160314_FanController_014

I was pleased to see that the fan connects to the main board by means of a standard two-pin 100mil header. So I could just plug anything in between the board and the fan.

20160313_FanController_005

That’s exactly what my first idea was. Stick with the original fan and just put a PWM controller in between. I’ve just recently made some LED dimmers and the technology needed here seemed to be very similar. So Rev A of my fan controller was born.

20160313_FanController_003

It’s simple: A linear 5V regulator, a PIC16F18325 microcontroller, an LMT86 temperature sensor and a N-channel mosfet. The PIC chosen here runs at up to 32MHz on an internal oscillator, has an internal voltage reference (of 1.024, 2.048 or 4.096V), six PWM modules and plenty of other nice features while comming in a small 14-pin package. So all I need to do is to measure the temperature, calculate the desired fan speed and set the PWM duty cycle accordingly.

20160313_FanController_008

My first surprise came when I first wanted to program the PIC. My trusted Mikroelectronika MikroC for PIC compiler doesn’t know that chip. And neither does my MikroProg programmer. So after a little bit of research I ordered a PICkit3 and downloaded the MPLAB IDE. As a nice side effect I can now also compile code for and program the fancier PICs like the DSPics and PIC32s. I might do that before long.

20160313_FanController_001

So I did the necessary programming (and debugging) and attached a small fan. It all worked but I had to chose a quite low PWM frequency in order to make the fan spin at lower duty cycles. And probably as a result of the low PWM frequency the motion of the fan didn’t look or sound very smooth.

20160313_FanController_006

With the larger fan from the supply things only got worse. I had to lower the PWM frequency even more into the tens of Hz range so it would spin at all. And even like this I couldn’t get it to run at low duty cycles. Of course, the low frequency caused nasty vibrations so I gave up on this approach. I read online that other people successfully use PWM on their fans but at least this model wasn’t happy to be PWM-dimmed. Does anybody know more about this? Was this an option in the old days before brushless motors were the norm? Is it that brushless motors aren’t unsuitable for this kind of control alltogether or does it depend on the specific model? Please use the comments section below if you can shead some light on this.

20160403_FanController_002

But I don’t give up easily so after a bit of research I ordered a four-wire fan conforming to the so-called Intel spec. Besides ground and +12V they have two control lines. A PWM line that lets you control the fan speed by means of a (25kHz nominally) PWM singal. And a so-called TACH singal that allows you to read the current fan speed. The PWM line has internal pull-ups to (depending on the fan) 3.3 or 5 volts so you just need to pull it low. The TACH signal needs an external pull-up resistor and gets pulled low by the fan twice per revolution. So you’re getting a digital signal with a frequency of twice the fan speed.

20160403_FanController_009

I ordered a EBM Papst 622/2 HHP which is the right size and somewhat more powerful than the original fan. The new board has a somewhat odd shape so I can use one of the fan’s mounting screws to mount the board as well. Note that all the copper has been removed around the mounting hole. The fan is attached to a heat sink which is grounded while our board runs on a split suply. So ground as our board sees it is not actually ground but a negative voltage so we have to be careful.

20160403_FanController_012

The new Rev B design runs on 3.3 volts in order to be compatible with any fan independent of the fan’s internal logic voltage. I’ve also used a different temperature sensor – a classic LM35.

20160409_FanController_018

Like the Rev A there is an LED to visually indicate what’s going on. There are also three pins on the microcontroller that are intended to be used as debug pins so I put some vias there to make it easy to connect a scope probe.

fancontrol_tach

Above you get an idea of what the TACH signal looks like. It’s a quite low frequency singal since there are only two pulses per rotation. So the measured 104Hz shown on the screenshot correspond to 3120 RPM.

fancontrol_37_degrees

Having a TACH signal to measure and three debug outputs to worry about made the software development somewhat more involved but it was well worth it. I’ve used the debug pins as follows:

  • Actual (i.e. mesured) fan speed. 100% corresponds to 10000RPM
  • Target fan speed. 100% corresponds to 10000RPM
  • Measured temperature. 100% corresponds to 100 degrees centigrade

So from the duty cycle measured by a scope you can easily read the speeds and temperature.

fancontrol_50_degrees

Of course this is only possible since there are some unused PWM modules left. But as I said, this PIC has 6 of them and only two are needed to measure the fan speed and another to control the fan.

fancontrol_27_degrees

The transfer function from temperature to fan speed can be freely defined in software. In the screenshots above the fan was running at 1500RPM up to a temperature of 30 degrees. Above that the speed would rise linearly until reaching its maximum of 9000RPM at a temperature of 55 degrees.

20160409_FanController_023

One could easily implement a PID control if one was so inclined but the slowly chaning nature of the temperature in such a setting makes this largely unnecessary so at least for now only the proportional part is taken into consideration when calculating the PWM frequency.

20160409_FanController_026

As you can see, the little board is nicely held in place by one of the fan mouning screws. By the way, the LED blinks roughtly once per second and its duty cycle corresponds to the target fan speed relative to the maximum fan speed of 9000RPM. So if the LED is on one-third of the time the target fan speed is one-third of the maximum speed or 3000RPM.

20160409_FanController_027

Unfortunately for my application, the supply senses the current consumed by the fan and shuts down if not enough current flows. This is probably a good idea and prevents the supply from possible damage if the fan is unplugged for example.

20160409_FanController_022

I found that it is possible to run the fan at a lower speed without the supply complaining but with fan speeds below about 4000RPM the there were conditions causing an error condition. So I ended up connecting a 1W 150ohms resistor in parallel to keep the supply happy even with the fan running at only 1500RPM.

20160409_FanController_025

I believe that my settings are very much on the safe side. At a a temperature of around 50 degrees measured inside the case the airflow matches the one of the original fan at max speed. But needless to say this kind of fiddling voids the warranty and is always done a one’s own risk. The reward is a supply that is now hardly audible and much more pleasant to use.

20160409_FanController_021

The zip file contains the eagle files, PDFs and software of both revisions.

Ultrasonic Anemometer Part 16: Testing the new driver circuit

20160303_AnemometerDriver__007

Last time I’ve presented my new design for the ultrasonic anemometer driver circuit. So now it’s time to see how it performs. If you’re new to this project you might want to check out the overview page or at least my last post.

20160303_AnemometerDriver__002

By now I had the time to build up the board and to do some testing. My main struggle was with the power supply. The linear regulator LM2931 comes in both fixed and variable voltage configurations. Unfortunately there is absolutely no way to tell them apart from their markings. So I accidentially used the variable voltage variant resulting in an almost 12 volts output voltage blowing up half of my circuit. I later noticed that I was out of 5V parts alltogether and had to use a LM7805 in a TO-92 package as you can see from the photo below.

20160303_AnemometerDriver__006

After having fixed the blown-up components, the circuit worked quite well. The first thing I did was to write some basic software for the PIC16F1936 to output a burst of40kHz PWM pulses every 2 milliseconds. After every burst the Axis and Direction signals are changed so the transducers take their turns in a clockwise order (North-East-South-West-…). The screenshot below shows part of such a burst sent from the South transducer. Note that the signal is a precise 40kHz with a duty cycle of 50% as it should be.

BasicOutputTest_withMeasurement

Below you see a full burst of 10 pulses. The number of pulses to send will be something to optimize in software once the hardware is finalized.

SendingCloseup

From the following screenshot you can nicely see how the transducers are selected by means of the Axis and Direction signals.  The microcontroller always outputs its PWM burst from the same pin. All the signal routing is controlled by means of these two signals so there is not much of a software burdon.

SendingOverview

So sending pulses is easy and works well. But that’s the easy part. Now let’s see how the circuit performs in receiving and amplifying singals.

Below you see a complete send-receive cycle. A number of pulses is sent (red) and somewhat later received (yellow) and amplified (green). Notice the different scales. Despite being only slightly larger in amplitude on the screen, the ampified signal is about 15 times larger in amplitude. Remember from the last post that the gain is controlled by a pot so this is just a temporary setting.

The distance between the transducers is 230mm so the time delay should be roughly 700us. Looking at the screenshot below this seems to be the case.

SendReceiveCloseup

Note that I’m sending much more pulses this time and that there is a larger-than-usual gap after the 18th pulse. As mentioned, I’m still experimenting with how many pulses should be sent and how. Here I’ve sent 18 pulsed plus 7 more pulses 180 degrees out-of-phase. My hope was that the received signal will decrease more rapidly in amplitude after reaching its peak which would make the peak easier to identify. This is still work in progress but I think this might be a simple way to improve the reliability of this wind meter.

Below you see an overview over a round of measurements. Note how different transducers produce different patterns. There seems to be quite a bit of manufacturing spread between them even though they are presumably from the same production lot.SendReceiveOverview

Now let’s look at these signals in a bit more detail. There is a significant amount of noise present in the received signal but it seems to be largely gone after the amplifier stage. The amplifier is a single op amp with a DC-coupled input and a pot acting as resistive divider setting the gain. That’s about as simple as it gets. There are no filters or anything up to this point. But the output looks nice and clean.ReceiveAmpoutCloseup2

Here’s a close up making this even easier to see. There are narrow spikes present in at the input but the limited slew rate of the op amp seems to filter them all out. So the output is clean as a whistle without any filtering. Much better than expected. Wow.

ReceiveAmpoutCloseup

If you’ve read my last post you know that there is a second op amp which I intended to use for a active band pass filter. But there seems to be no need for that at all. Simplifies the circuit, saves an op amp as well as quite a bit of board space. Great.

Nevertheless you might have noticed that there is a wider and much larger spike in the received signal every time the axis and direction signals change. The cause of this is most likely charge injection through the p-cannel Mosfets that are used as switches between the Mosfet drivers and the transducer. ReceiveSpikeCloseup

Being much slower and wider than the noise we’ve looked at so far, this spike makes through the amplifier with only slight attenuation. The good thing is that this spike occurs when we switch from one transducer to the next. That’s a time when we won’t want to look at the received singal anyway. We haven’t even sent any pulses yet. The spike abates long before the received singal starts being of interest. So I’m confident that this spike causes no real harm and can savely be ignored.

20160303_AnemometerDriver__001

All in all I’m positively surprised how well this design has performed. I’m obviously getting a much stronger gate drive of 12 volts as opposed to 5 volts with my old design. And not only that. The Mosfet drivers used can source and sink several amps so there is reason to hope that the signal is not only larger in amplitude but also cleaner and more square. I’ll have to look at the shape of the wave form at the transducers in more detail to verify if this is really the case.

20160303_AnemometerDriver__003

But I’m most surprised of how well the simple op amp performs. Using this super-simple setup I’m getting an output signal that’s just as clean as what I got from the rather complex two-stage tuned common emitter amplifier. No need to tune this thing making it much more production friendly. And it saves plenty of board space as well.

20160303_AnemometerDriver__009

So this is the way to go I think. The next step will be to come up with some circuitry to process the received and amplified signal. I have some ideas in my mind and will elaborate on them shortly. But first I’ll take a closer look at the new lasercut mechanical design.