Last night, I thought about the fact that the new display module I have been sent, with its driver circuitry, only uses 4 pins rather than the 12 I was expecting on the naked 4 digit LED. That means that I can connect the display module, the HC-SR04 ultrasonic sensor, AND the DS3231 RTC to the Uno all at the same time (and still have pins to spare). By shuffling things up a bit on my breadboard, I could fit the RTC module alongside the ultrasonic module, so that a) it has a semi-permanent home and I don't have to worry about it getting shorted out any more, and b) I can use the display for either the clock or the rainwater tank gauge just by reloading the required sketch. So I set to, and did just that.
Unfortunately, the combination of my poor eyesight, low light in the evening, and trying to line up small cables with small holes means - inevitably - I did something wrong - with style and panache! Actually, it turns out I did a couple of somethings wrong, but please, read on...
Eager to see if the RTC was still keeping time after a week in its little bag, I plugged it all in and reloaded my little clock sketch. Nothing... Zip... Nada! Well - what a let down. So, hoping I had simply dislodged a wire to the display, I reloaded the tank gauge sketch as a test, but that worked OK. I tried the clock again, but still nothing. So it must be the RTC wiring or the RTC itself
I decided to pull out the RTC and the DuPont cables to it and start again. I grabbed the RTC and burned my thumb on the battery - it was very hot! I figured this meant I had a power problem and quickly found that I had reversed the Vcc and GND connections to the RTC board... I'm really surprised I hadn't buggered up everything else on the breadboard - my Uno included!
Anyway - I removed the battery and let everything cool down and swapped the connections back the way they should be, then tried again. This time, the display came back to life (whoopee!), but I was a little disappointed and somewhat surprised to see the time was 13:65!
I guess that just maybe, reversing the polarity and almost setting fire to the module may have had a slightly adverse affect on the data - possibly - so I reloaded the set time sketch, reset the time and tried again. It was still showing 13:65 - weird... Uh oh - I started to get that feeling of dread again - you know, the one I got just seconds after hitting the button to buy a Pro Mini that I realised I knew nothing about..? After the first RTC I bought being DOA, perhaps I've now killed this RTC as well.
I reloaded the tank gauge sketch, just to make sure I hadn't fried the Uno as well, but that seemed to be working OK. I tried the clock once more - and the time was still 13:65 - DAMMIT! What was worse, was that the time display seemed static - even after 5 minutes (carefully keeping an eye on the temperature of the battery), it was still apparently 13:65 - I kind of hoped it might tick over each minute and show 13:70.
Well - I had removed and reseated the RTC module, and the Vcc/GND wires had been swapped, but I hadn't touched the SDA and SCL cables yet... Yes, you've guessed it - I had them round the wrong way too! Good grief, just how much wronger (yes - its a word) could I possibly have got this? After swapping those two around, and running the set sketch again, the display finally shows the correct time. Just to make sure, I pulled the rest of the clock data (YYMMDD, DoW, and hhmmss) and displayed them on the Serial console - phew - all seems ok. I haven't destroyed the chip after all, despite my best efforts. Mind you, having abused the battery like that, I'm not sure how long that is going to last now. It has kept the RTC going for around 24 hrs at the time of writing this, and the time is still correct to within about a second. I'm just counting my blessings, and vow that I am not going to touch that module again until it goes into its permanent home on my portable workbench.
Lesson learned? Accept that I'm getting older and my eyesight ain't what it used to be. Don't struggle in dim light where you can't see the difference between a grey and lilac cable, or manage to line up the red and black cables with the appropriate pins on the Uno... TURN SOME LIGHTS ON!
An introduction to basic elctronics, and designing circuits and programs to be used with an Arduino microcontroller board such as the Arduino Uno. Learn with me as I take things apart, investigate, research, and gradually build my own knowledge.
Thursday, 9 November 2017
Thursday, 2 November 2017
Water Tank Depth Gauge - 3 (The Prototype)
Last night, I dismantled my clock (carefully placing the DS3231 RTC in a bag to prevent any accidental short-circuiting), and cobbled together the Uno, HC-SR04 ultrasonic sensor, and my (clock oriented) 4 digit LED, to make a very nerdy looking ultrasonic tape measure (Dr Who - eat your heart out - sonic screwdriver, pah!).
I kept the code very basic (in fact, it is less than 50 lines of code including comments and spacing), and this quick and dirty version just shows the distance measured in cms on the display.
I did a few random measuring experiments, and was quite impressed with the apparent accuracy! I haven't yet set up a test rig to check measurements across the entire range, but I did a few spot checks and found it to be within 1-2 cms at distances up to a couple of metres, though I have noticed occasional sporadic and momentary wild readings. For example, while writing this, the sofa across the other side of the room is apparently 3.44 metres away - most of the time, but once in a while, just for a split second, it leaps forwards to 3.01 or even 2.88 metres, and immediately jumps back again! Perhaps I shouldn't have made that comment about Dr Who... I think he is getting his own back, by playing around with my interspatial dimensionality continuum :-/ Or maybe it is just soft furnishings don't give a solid enough echo...
The ebay seller has agreed to send me a new display unit (he thinks his 'worker' has made a mistake), and says he will find a way to get the replacement to me quickly so I don't have to wait another 3-4 weeks. Now I just hope that his 'worker' has actually understood the mistake, and doesn't just send the same thing again. Oh well, if he does, then I'll just use it to display the 3 digit number and have a spare clock display I can mount onto my portable workbench.
I kept the code very basic (in fact, it is less than 50 lines of code including comments and spacing), and this quick and dirty version just shows the distance measured in cms on the display.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | #include <TM1637Display.h> #include <NewPing.h> // LED Module connection pins (Digital Pins) #define CLK 9 #define DIO 8 // pins for HC-SR04 #define pinTrig 6 #define pinEcho 7 NewPing sonar(pinTrig, pinEcho, 400); // 400 is max claimed ability, though it actually keeps going till around 450 // Initialise LED TM1637Display display(CLK, DIO); void setup() { // setup the sonar pins pinMode(pinTrig, OUTPUT); pinMode(pinEcho, INPUT); // turn off annoying LED on 13 pinMode(13, OUTPUT); digitalWrite(13,LOW); // set brightness of LED // (0-7,true/false) where 0=min 7=max (0-3 have greatest impact), true=on and false=off display.setBrightness(1,true); // set all segments off for all digits uint8_t data[] = { 0x00, 0x00, 0x00, 0x00 }; display.setSegments(data); } void loop() { // Take 10 readings, and use median duration. int duration = sonar.ping_median(10); // duration is in microseconds // Convert the averaged delay time to distance (water surface to sensor). int cms = duration / 29 / 2; // speed of sound is 29 microsecs per cm (x2 for round trip) // display distance on LED display.showNumberDec(cms,false,4,4); } |
I did a few random measuring experiments, and was quite impressed with the apparent accuracy! I haven't yet set up a test rig to check measurements across the entire range, but I did a few spot checks and found it to be within 1-2 cms at distances up to a couple of metres, though I have noticed occasional sporadic and momentary wild readings. For example, while writing this, the sofa across the other side of the room is apparently 3.44 metres away - most of the time, but once in a while, just for a split second, it leaps forwards to 3.01 or even 2.88 metres, and immediately jumps back again! Perhaps I shouldn't have made that comment about Dr Who... I think he is getting his own back, by playing around with my interspatial dimensionality continuum :-/ Or maybe it is just soft furnishings don't give a solid enough echo...
The ebay seller has agreed to send me a new display unit (he thinks his 'worker' has made a mistake), and says he will find a way to get the replacement to me quickly so I don't have to wait another 3-4 weeks. Now I just hope that his 'worker' has actually understood the mistake, and doesn't just send the same thing again. Oh well, if he does, then I'll just use it to display the 3 digit number and have a spare clock display I can mount onto my portable workbench.
Tuesday, 31 October 2017
A fortuitous ebay mistake
Today, my ultrasonic sensor arrived with the 4 digit display. BUT - instead of the bare 4 digit display, they sent me a display module with a 4 pin interface, which is good, but it is a clock module with a colon in the middle, rather than normal digits - each with a decimal point.
After a little digging around, I have found a library to drive the module and figured out how to use it. As it happens - since I wouldn't need a decimal point, I could use this module in the water tank gauge project, but I have already pointed out the mistake to the seller, in the hope he will send me a new display of the type shown in the ebay listing.
But as I now have an LED display geared up for a clock type display, I thought - why not pair it up with my new RTC module and have a little clock. Ok - so it only shows hours and minutes, but it will help me to test the longevity of the 2032 battery in the DS3231.
Here is my code for the clock
I have tried forcing the hours to am/pm mode, as the RTC always seems to show it in 24 hour format (I expect there is a way to do it using the library functions, but I didn't find it yet), and then apply leading zero suppression to the hours, so that it shows as 9:00 for example, rather than 09:00. However, I'm not sure what'll happen between midnight and 1am - perhaps the hour will not show at all...? I won't be awake to see it though - at least not tonight!
I have no clue why the mask that controls the colon being displayed works... it is a bitwise shift right by three places, but by my reckoning, as the left most bit in the mask is a shift of 0, then the mask should be using a shift of either 1 or 2 places (depending if the colon is linked to the right side of digit 2 or the left side of digit 3. But - I got it working by trial and error, and have even managed to make it flash every second.
Tomorrow, hopefully, I may start playing with the ultrasonic sensor unit. Exciting!!
Update - 2 days later:
The RTC is still holding the time well. I did originally have some issues with it randomly resetting itself, but I think was down to my dodgy prototyping with modules just hanging off the Uno on the end of DuPont cables - things were possibly touching other things and shorting out, etc. After I blu-tacked all the modules down on a base board - no more problems.
By the way - even with leading zero suppression, times between midnight and 1 o'clock DO show with a single zero for the hour, as I hoped.
Update - 3 weeks later:
It is still holding the time, but given that my display is only hours and minutes, I haven't confirmed just how accurate the time is. But the fact it still has a valid time that is even roughly correct is a big win.
After a little digging around, I have found a library to drive the module and figured out how to use it. As it happens - since I wouldn't need a decimal point, I could use this module in the water tank gauge project, but I have already pointed out the mistake to the seller, in the hope he will send me a new display of the type shown in the ebay listing.
But as I now have an LED display geared up for a clock type display, I thought - why not pair it up with my new RTC module and have a little clock. Ok - so it only shows hours and minutes, but it will help me to test the longevity of the 2032 battery in the DS3231.
Here is my code for the clock
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | #include <DS3231.h> #include <TM1637Display.h> // Module connection pins (Digital Pins) #define CLK 9 #define DIO 8 // Initialise LED TM1637Display display(CLK, DIO); // Initialise RTC & RTC variables DS3231 Clock; bool Century=false; bool h12; bool PM; byte ADay, AHour, AMinute, ASecond, ABits; bool ADy, A12h, Apm; // other variables long counter; uint8_t mask = 0b00010000; void setup() { // turn off annoying LED on 13 pinMode(13, OUTPUT); digitalWrite(13,LOW); // set brightness of LED display.setBrightness(0x0f); // set all segments off for all digits uint8_t data[] = { 0x00, 0x00, 0x00, 0x00 }; display.setSegments(data); // store current millis() counter = millis(); } void loop() { // get Time from RTC int hrs = Clock.getHour(h12,PM); int mins = Clock.getMinute(); if (hrs > 12) hrs -= 12; // display the hours with colon enabled/disabled as each second passes // mask for colon on digit 2 // 0x80>>3 = 0b00010000 (I have no idea WHY this works!) if (millis() - counter > 1000) { if (mask == 0b00010000) { mask = 0b00000000; } else { mask = 0b00010000; } counter = millis(); } display.showNumberDecEx(hrs,mask,false,2,0); // display the minutes display.showNumberDec(mins,true,2,2); } |
I have tried forcing the hours to am/pm mode, as the RTC always seems to show it in 24 hour format (I expect there is a way to do it using the library functions, but I didn't find it yet), and then apply leading zero suppression to the hours, so that it shows as 9:00 for example, rather than 09:00. However, I'm not sure what'll happen between midnight and 1am - perhaps the hour will not show at all...? I won't be awake to see it though - at least not tonight!
I have no clue why the mask that controls the colon being displayed works... it is a bitwise shift right by three places, but by my reckoning, as the left most bit in the mask is a shift of 0, then the mask should be using a shift of either 1 or 2 places (depending if the colon is linked to the right side of digit 2 or the left side of digit 3. But - I got it working by trial and error, and have even managed to make it flash every second.
Tomorrow, hopefully, I may start playing with the ultrasonic sensor unit. Exciting!!
Update - 2 days later:
The RTC is still holding the time well. I did originally have some issues with it randomly resetting itself, but I think was down to my dodgy prototyping with modules just hanging off the Uno on the end of DuPont cables - things were possibly touching other things and shorting out, etc. After I blu-tacked all the modules down on a base board - no more problems.
By the way - even with leading zero suppression, times between midnight and 1 o'clock DO show with a single zero for the hour, as I hoped.
Update - 3 weeks later:
It is still holding the time, but given that my display is only hours and minutes, I haven't confirmed just how accurate the time is. But the fact it still has a valid time that is even roughly correct is a big win.
Wednesday, 25 October 2017
Success Squared
Yep - I had two successes last night when I started my tinkering.
Firstly, after soldering pins onto the Pro Mini, I was able (eventually) to use the Uno to load a sketch to it (it came with bootloader and blink sketch already loaded). But this was not quite the 'piece of cake' I predicted. I have header pins on the Pro Mini, allowing easy connection to pins 11-13, Vcc, Gnd, and Rst. Because of the ISP indicator lights widget, pins 10-13 on my Uno are not accessible, so I thought I'd be clever and connect the Pro Mini to the ISP6 pins on my Uno. That's when the problems started. While 'Arduino as ISP' loaded on my Uno, I couldn't get it to load a modified blink sketch to the Pro Mini. The error was something like 'unknown board id'. I removed the 6 connections at both ends and did them again (and again just for good measure), but with the same result. I went back out to the garage, and re-flowed the solder joins on my Pro Mini header pins - and also the 16MHz crystal as one of the joints looked a little suspect. Still no joy. I was about to head out to the garage for a third time, to try and find a capacitor to put between Reset and Ground on my Uno, when I decided to take out the status lights widget and try making the connections from pins 10-13, Vcc, and Gnd on the Uno rather than the ISP6 block - and it worked! Go figure - I have no idea why - as far as I knew, they should be connected to the same pins on the 328P chip... Anyway - I'm not going to argue the point - I'm just happy that I now have a tried and proven mechanism to download sketches to the Pro Mini. Unfortunately, I will have to either modify my little ISP status lights widget to free up access to pins 10-13, or just solder the second row of header pins onto my Uno - I guess that's a simpler and probably more useful option.
The second success was with my DS3231 RTC. I downloaded a library for it, and it has several example sketches - a very simple 'Set' process, which I ran and managed to enter a time that was just 3 seconds away from my cell phone's time. Then I used a basic 'Get' example that wrote the details back to the serial console. I stuffed a CR2032 battery in the RTC, and then unplugged everything, and started it up again running the 'Get' script, and it was still just 3 seconds from my phone. Next, I found one of my old sketches that I used to test the DS1302, that uses my LCD 20x4 display, and did some quick hacks on that so I can run the script without needing to be connected to the computer for serial output. Again, I left it all unplugged overnight, and fired up the Uno, LCD and RTC simply with a 9v battery this morning - and it was still just 3 seconds from my phone. Yay!!
So the next project with the RTC is to create a nice 'Set Date and Time' sketch that uses the LCD rather than the serial input from the console, and that allows for minor adjustments, and 1 hour advance and retard operations for daylight savings. Then I want to experiment and understand the benefits of simply using the RTC lib on its own, as opposed to using the Time lib and 'syncing' to the RTC. I want to find the simplest way possible, that I can use the time from my RTC in my projects, and then to use it consistently, rather than every project using a different combination of libraries and commands to handle time. There seem to be endless different ways with different libraries and so on.
Postscript...
I spoke too soon. Came home this evening and switched on the Uno again, and boy - what a load of cobblers came up on the screen! I reset it and rebooted it, but still rubbish. However, I noticed that it kept initialising to exactly the same load of cobblers each time. So I took the battery out of the RTC and tried again, and it was still booting to the same point each time, until eventually, it started booting to 01/01/2000 at 00:00:00. So I'm hoping that all this means is that the battery I had was at the end of its life - it had been recovered from the motherboard of an old PC after all. I'll try again with a fresh battery tomorrow.
Firstly, after soldering pins onto the Pro Mini, I was able (eventually) to use the Uno to load a sketch to it (it came with bootloader and blink sketch already loaded). But this was not quite the 'piece of cake' I predicted. I have header pins on the Pro Mini, allowing easy connection to pins 11-13, Vcc, Gnd, and Rst. Because of the ISP indicator lights widget, pins 10-13 on my Uno are not accessible, so I thought I'd be clever and connect the Pro Mini to the ISP6 pins on my Uno. That's when the problems started. While 'Arduino as ISP' loaded on my Uno, I couldn't get it to load a modified blink sketch to the Pro Mini. The error was something like 'unknown board id'. I removed the 6 connections at both ends and did them again (and again just for good measure), but with the same result. I went back out to the garage, and re-flowed the solder joins on my Pro Mini header pins - and also the 16MHz crystal as one of the joints looked a little suspect. Still no joy. I was about to head out to the garage for a third time, to try and find a capacitor to put between Reset and Ground on my Uno, when I decided to take out the status lights widget and try making the connections from pins 10-13, Vcc, and Gnd on the Uno rather than the ISP6 block - and it worked! Go figure - I have no idea why - as far as I knew, they should be connected to the same pins on the 328P chip... Anyway - I'm not going to argue the point - I'm just happy that I now have a tried and proven mechanism to download sketches to the Pro Mini. Unfortunately, I will have to either modify my little ISP status lights widget to free up access to pins 10-13, or just solder the second row of header pins onto my Uno - I guess that's a simpler and probably more useful option.
The second success was with my DS3231 RTC. I downloaded a library for it, and it has several example sketches - a very simple 'Set' process, which I ran and managed to enter a time that was just 3 seconds away from my cell phone's time. Then I used a basic 'Get' example that wrote the details back to the serial console. I stuffed a CR2032 battery in the RTC, and then unplugged everything, and started it up again running the 'Get' script, and it was still just 3 seconds from my phone. Next, I found one of my old sketches that I used to test the DS1302, that uses my LCD 20x4 display, and did some quick hacks on that so I can run the script without needing to be connected to the computer for serial output. Again, I left it all unplugged overnight, and fired up the Uno, LCD and RTC simply with a 9v battery this morning - and it was still just 3 seconds from my phone. Yay!!
So the next project with the RTC is to create a nice 'Set Date and Time' sketch that uses the LCD rather than the serial input from the console, and that allows for minor adjustments, and 1 hour advance and retard operations for daylight savings. Then I want to experiment and understand the benefits of simply using the RTC lib on its own, as opposed to using the Time lib and 'syncing' to the RTC. I want to find the simplest way possible, that I can use the time from my RTC in my projects, and then to use it consistently, rather than every project using a different combination of libraries and commands to handle time. There seem to be endless different ways with different libraries and so on.
Postscript...
I spoke too soon. Came home this evening and switched on the Uno again, and boy - what a load of cobblers came up on the screen! I reset it and rebooted it, but still rubbish. However, I noticed that it kept initialising to exactly the same load of cobblers each time. So I took the battery out of the RTC and tried again, and it was still booting to the same point each time, until eventually, it started booting to 01/01/2000 at 00:00:00. So I'm hoping that all this means is that the battery I had was at the end of its life - it had been recovered from the motherboard of an old PC after all. I'll try again with a fresh battery tomorrow.
Labels:
Arduino as ISP,
clock,
DS1302,
DS3231,
electronics,
ISP,
Pro Mini,
RTC
Tuesday, 24 October 2017
Water Tank Depth Gauge - 2
Time has passed, and the first few of my new batch of components arrived in this morning's post - well, the Pro Mini for this project has arrived at least (but I also treated myself to some 4-pin DuPont cables for IIC device connections, and another RTC after the DS1301 proved to be cr@p, so I've now got an IIC DS3231 board, which I hope will be better - or at least work!!).
In the intervening time, I've made a start on developing the code for my gauge. It consists mainly of 3 parts - the first part deals with the sensor itself, getting the 'ping' reading (which is the echo return time in microseconds), and converting that into the sensor-to-water distance in cms. From this measurement, and knowing the distance from the sensor to the highest and lowest water levels of the tank, I can work out the percentage capacity used or remaining in the tank.
As an afterthought, I've also included a HIGH/LOW test on a pin I've called OpMode, which I will connect to a 3-pin header with a jumper allowing it to be connected to Vcc or GND. This will facilitate the display of either the percentage value (as described above), or the actual distance measured. This second mode will allow me calibrate the unit, as I am not convinced it will be accurate to 3mm as claimed by the manufacturer. In fact I have seen many articles that show errors of several cms, even at just half the suggested max 400cm capability of the unit. Remembering that all my purchases are of cheap (and therefore most likely 'seconds' quality, or poor quality knock-offs) Chinese ebay items, so I am fully expecting to need to add some correction factors in once I have all the parts and can do some testing. I'll probably put up a post showing my results when I have all the parts and can do some controlled experiments.
The second section of my code simply takes the resulting number (either a distance in cms, or percentage), and breaks it down into individual digits - hundreds, tens, and units. This means I will only use a maximum 3 of the 4 digits on the LED, so I can use the 4th to indicate the OpMode (test/normal). Note - if the first digit is 0, I want to display nothing on that digit in the display, rather than prefixing the rest of the number with a zero.
The third part then takes each of the three digits and OpMode, and displays them on the LED digits 1-4 sequentially. The LED is a common cathode device, which means that you can display the same value on all 4 digits at the same time, but if you want each to show a different value, then you have to do them one at a time. Switch on digit 1 and light up all the correct segments; wait very briefly; then switch them all off again and move on to digit 2 and repeat. The trick is to do this while looping around all 4 digits fast enough to make it appear they are all being displayed simultaneously. I have done this by creating a subroutine called displayDigit, and passing it the digit to activate, and the value to be displayed, and placing 3 calls to it from the loop() subroutine.
In relation to my suspected faux pas regarding buying the Pro Mini board without an ISP interface board to program it, I am pleased to say that further research has reveled that the articles I referred to previously, whilst giving me hope of potential work-arounds, were perhaps over-complicating the procedure. Thanks to Julian Ilett's youtube video - Arduino as an ISP, it looks like using an existing Arduino to load a sketch OR a bootloader to the Pro Mini or any other xxuino device, is a piece of cake! I love Julian's videos - he has a great way of explaining things. If you watched this video, I have already cobbled together my own version of his 3 LED ArduinoISP monitoring widget, and have installed the sketch on my Uno so I can watch the heartbeat.
For those that haven't yet watched it, there is a 2 stage process for loading a sketch or bootloader to a second device... Since I am using my Uno as the programmer, and Pro Mini as the target, I'll use these in my description below, but the concept holds true for programming any target xxuino from any programmer xxuino (as far as I can tell) though the specific pin connections may vary from device to device - especially if they don't have an ISP6 6-pin block and you are having to use digital pin equivalents.
So the first step is to load the "ArduinoISP" sketch onto my Uno, in exactly the same way I load normal sketches, to turn it into a pass-thru ISP controller. The second step is to load my water gauge sketch into the IDE, then select Pro Mini as the board. Now, rather than the normal compile and upload operation, go to Tools/Programmer and select the "Arduino as ISP" option. This compiles the sketch in the IDE and passes the compiled code to the sketch that is running on the Uno. This sketch allows for a stream of compiled code to be received from the IDE, but NOT loaded into memory by the bootloader. Instead, it passes the compiled code on to the Pro Mini where its bootloader DOES store it in the Pro Mini's memory, ready to go when disconnected from the Uno and given its own power supply.
In case you need to actually install the bootloader on the Pro Mini, then when you have the ArduinoISP sketch loaded on the Uno, select the Pro Mini as the target board again, then go to Tools/Programmer, and use the "Install Bootloader" option. I am not 100% sure if the first step is really required, but I think that without it, you may end up potentially screwing the bootloader on the Uno or have the whole operation fail because the IDE see's an Uno board at the other end of the USB cable, rather than leap-frogging to the Pro Mini selected. Personally - I'm not game to test out my theory - but if you are adventurous, go ahead and try, and let me know what happens in the comments below.
OK - So, now I just want to get the rest of my day at work over and done with , so I can get home and start tinkering this evening - first job, connect header pins to Pro Mini so I can plug it into my breadboard and see if it has a bootloader and 'blink' sketch loaded :)
In the intervening time, I've made a start on developing the code for my gauge. It consists mainly of 3 parts - the first part deals with the sensor itself, getting the 'ping' reading (which is the echo return time in microseconds), and converting that into the sensor-to-water distance in cms. From this measurement, and knowing the distance from the sensor to the highest and lowest water levels of the tank, I can work out the percentage capacity used or remaining in the tank.
As an afterthought, I've also included a HIGH/LOW test on a pin I've called OpMode, which I will connect to a 3-pin header with a jumper allowing it to be connected to Vcc or GND. This will facilitate the display of either the percentage value (as described above), or the actual distance measured. This second mode will allow me calibrate the unit, as I am not convinced it will be accurate to 3mm as claimed by the manufacturer. In fact I have seen many articles that show errors of several cms, even at just half the suggested max 400cm capability of the unit. Remembering that all my purchases are of cheap (and therefore most likely 'seconds' quality, or poor quality knock-offs) Chinese ebay items, so I am fully expecting to need to add some correction factors in once I have all the parts and can do some testing. I'll probably put up a post showing my results when I have all the parts and can do some controlled experiments.
The second section of my code simply takes the resulting number (either a distance in cms, or percentage), and breaks it down into individual digits - hundreds, tens, and units. This means I will only use a maximum 3 of the 4 digits on the LED, so I can use the 4th to indicate the OpMode (test/normal). Note - if the first digit is 0, I want to display nothing on that digit in the display, rather than prefixing the rest of the number with a zero.
The third part then takes each of the three digits and OpMode, and displays them on the LED digits 1-4 sequentially. The LED is a common cathode device, which means that you can display the same value on all 4 digits at the same time, but if you want each to show a different value, then you have to do them one at a time. Switch on digit 1 and light up all the correct segments; wait very briefly; then switch them all off again and move on to digit 2 and repeat. The trick is to do this while looping around all 4 digits fast enough to make it appear they are all being displayed simultaneously. I have done this by creating a subroutine called displayDigit, and passing it the digit to activate, and the value to be displayed, and placing 3 calls to it from the loop() subroutine.
In relation to my suspected faux pas regarding buying the Pro Mini board without an ISP interface board to program it, I am pleased to say that further research has reveled that the articles I referred to previously, whilst giving me hope of potential work-arounds, were perhaps over-complicating the procedure. Thanks to Julian Ilett's youtube video - Arduino as an ISP, it looks like using an existing Arduino to load a sketch OR a bootloader to the Pro Mini or any other xxuino device, is a piece of cake! I love Julian's videos - he has a great way of explaining things. If you watched this video, I have already cobbled together my own version of his 3 LED ArduinoISP monitoring widget, and have installed the sketch on my Uno so I can watch the heartbeat.
For those that haven't yet watched it, there is a 2 stage process for loading a sketch or bootloader to a second device... Since I am using my Uno as the programmer, and Pro Mini as the target, I'll use these in my description below, but the concept holds true for programming any target xxuino from any programmer xxuino (as far as I can tell) though the specific pin connections may vary from device to device - especially if they don't have an ISP6 6-pin block and you are having to use digital pin equivalents.
So the first step is to load the "ArduinoISP" sketch onto my Uno, in exactly the same way I load normal sketches, to turn it into a pass-thru ISP controller. The second step is to load my water gauge sketch into the IDE, then select Pro Mini as the board. Now, rather than the normal compile and upload operation, go to Tools/Programmer and select the "Arduino as ISP" option. This compiles the sketch in the IDE and passes the compiled code to the sketch that is running on the Uno. This sketch allows for a stream of compiled code to be received from the IDE, but NOT loaded into memory by the bootloader. Instead, it passes the compiled code on to the Pro Mini where its bootloader DOES store it in the Pro Mini's memory, ready to go when disconnected from the Uno and given its own power supply.
In case you need to actually install the bootloader on the Pro Mini, then when you have the ArduinoISP sketch loaded on the Uno, select the Pro Mini as the target board again, then go to Tools/Programmer, and use the "Install Bootloader" option. I am not 100% sure if the first step is really required, but I think that without it, you may end up potentially screwing the bootloader on the Uno or have the whole operation fail because the IDE see's an Uno board at the other end of the USB cable, rather than leap-frogging to the Pro Mini selected. Personally - I'm not game to test out my theory - but if you are adventurous, go ahead and try, and let me know what happens in the comments below.
OK - So, now I just want to get the rest of my day at work over and done with , so I can get home and start tinkering this evening - first job, connect header pins to Pro Mini so I can plug it into my breadboard and see if it has a bootloader and 'blink' sketch loaded :)
Wednesday, 11 October 2017
Water Tank Depth Gauge - 1
I've got a 2000 litre rainwater tank by my garage (actual usable capacity is around 1750), but it is really difficult to know just how much water remains in it at any time, so I am going to try and build a depth gauge based on an ultrasonic sounder that I can hold at the top opening of the tank, and measure the distance from there to the surface of the water. Once I have that, the rest is just maths.
I initially fancied mounting the sounder permanently inside the top of the tank, with the display inside my garage - but I fear that the humidity and condensation in the tank would probably very quickly render the sounder unit useless, or at the very least, it would drop into the water. So I am now thinking of making a 'portable' unit that will be mounted to a bar that can be placed across the opening into the tank, thus providing a consistent starting point for the measurement to be taken each time.
I have ordered an HC-SR04 ultrasonic sounder from eBay, that also comes with a 4-digit 7-segment LED display. That takes care of the measuring and displaying of the output. I also decided to buy the cheapest xxduino device I could find, which I could therefore afford to have dedicated to this specific project... I found and ordered an Arduino Pro Mini device, without really knowing too much about them. Luckily, it only cost $2.20, as subsequent investigations and planning my project have revealed I may have made a booboo, and could face some difficulties with it...
The Pro Mini I have purchased is by happy accident, the 5v version, so I won't have any power woes (I later found there is also a 3.3v variant, and combining the 3.3v version with the 5v requirement of the sounder and display would have meant dual voltage complications) , BUT more frightening - I suddenly realised that this board has no USB connector on it... I had ordered the wrong item in my excitement - I had meant to order a Nano which DID have the USB connector. I had a sudden feeling of dread - how am I supposed to program and test this thing?
Well, some late night research was done so I wouldn't have to admit to my blunder, and I think I may be OK (but only time will tell). Thankfully, I have found a couple of "Instructables" articles aimed at using my Uno as a middle man between my PC and the Pro Mini, without having to remove the ATMega chip from the Uno (there were plenty of articles that relied on removing the ATMega328 chip, but this is not really a practical proposition on mine, as it has the small form factor surface mounted chip soldered directly on the board). One of these articles shows how to use the Uno as an ISP to burn a new bootloader to the Pro Mini if required without needing an FTDI board (sure enough, subsequent readings of the seller's notes makes no mention of a bootloader having been installed...), and the other explains how to load sketches to the Pro Mini using USB from PC to Uno, and then Serial (TX/RX) from the Uno to the Pro Mini. So, fingers crossed, I will be able to set these connections up semi-permanently while I am testing and developing my gauge, and just disconnect them once I am happy with the final programming.
As always - having ordered these things from China, it will be about 4-6 weeks before I actually receive them (and a few other bits I ordered at the same time), so I don't know when the next instalment of this project will appear. Watch this space...!
I initially fancied mounting the sounder permanently inside the top of the tank, with the display inside my garage - but I fear that the humidity and condensation in the tank would probably very quickly render the sounder unit useless, or at the very least, it would drop into the water. So I am now thinking of making a 'portable' unit that will be mounted to a bar that can be placed across the opening into the tank, thus providing a consistent starting point for the measurement to be taken each time.
I have ordered an HC-SR04 ultrasonic sounder from eBay, that also comes with a 4-digit 7-segment LED display. That takes care of the measuring and displaying of the output. I also decided to buy the cheapest xxduino device I could find, which I could therefore afford to have dedicated to this specific project... I found and ordered an Arduino Pro Mini device, without really knowing too much about them. Luckily, it only cost $2.20, as subsequent investigations and planning my project have revealed I may have made a booboo, and could face some difficulties with it...
The Pro Mini I have purchased is by happy accident, the 5v version, so I won't have any power woes (I later found there is also a 3.3v variant, and combining the 3.3v version with the 5v requirement of the sounder and display would have meant dual voltage complications) , BUT more frightening - I suddenly realised that this board has no USB connector on it... I had ordered the wrong item in my excitement - I had meant to order a Nano which DID have the USB connector. I had a sudden feeling of dread - how am I supposed to program and test this thing?
Well, some late night research was done so I wouldn't have to admit to my blunder, and I think I may be OK (but only time will tell). Thankfully, I have found a couple of "Instructables" articles aimed at using my Uno as a middle man between my PC and the Pro Mini, without having to remove the ATMega chip from the Uno (there were plenty of articles that relied on removing the ATMega328 chip, but this is not really a practical proposition on mine, as it has the small form factor surface mounted chip soldered directly on the board). One of these articles shows how to use the Uno as an ISP to burn a new bootloader to the Pro Mini if required without needing an FTDI board (sure enough, subsequent readings of the seller's notes makes no mention of a bootloader having been installed...), and the other explains how to load sketches to the Pro Mini using USB from PC to Uno, and then Serial (TX/RX) from the Uno to the Pro Mini. So, fingers crossed, I will be able to set these connections up semi-permanently while I am testing and developing my gauge, and just disconnect them once I am happy with the final programming.
As always - having ordered these things from China, it will be about 4-6 weeks before I actually receive them (and a few other bits I ordered at the same time), so I don't know when the next instalment of this project will appear. Watch this space...!
Thursday, 28 September 2017
Breadboard Power Supply
Remember the power supply that I bought for my breadboard, because it was just a dollar? Yes, that's right - the one I blew up! Well my subsequent investigations into potentially mending it revealed some interesting information to me.
Of course, the first thing I found out is that many of the mains powered DC supplies that come with devices like your broadband modem, cable set-top box, Yamaha electronic keyboard... and so on, are what are called 'unregulated'. This means that while the specs panel on them might say something like 'DC Out : 12v @ 1000mA', what that means is that even if you are drawing 1000mA from it, the unit should still manage to deliver 12 volts. However, to achieve this and avoid the extra component costs of building a regulator into the unit, if you are drawing just a few mA from it, then the unit will generally deliver way over 12 volts, perhaps as much as 50% over - that's 18 volts!!
As my breadboard power supply regulator said it would take an input of up to 12 volts, and I had already used it successfully with a normal PP3 9 volt battery, I felt quite safe connecting it to my 9v @ 1000mA DC supply. Oops - what a 'noob' thing to do. I switched on the breadboard supply, which drew maybe 50mA with nothing except its on board LED and my multimeter connected across it, and shot about 14 volts straight into the regulator - which objected strongly, and let about 10 volts out the other side on what should have been the 5 volt line. Lucky I didn't have anything sensitive plugged into the breadboard!
Now, strangley enough, the 3.3 volt regulator still worked perfectly at the time. So a little while later, having obtained a replacement board (well, it was just a dollar...), I thought that I would remove the surface mounted 5 volt regulator chip - with a view to eventually replacing it - maybe. In the meantime, the absence of that chip would help me identify which board was fully functional, and which could only be trusted at 3.3 volts.
After setting to work with the soldering iron, the chip came off the board easily, and... the 3.3 volt regulator stopped working! Ugh - I threw my hands up in disgust, and threw the power supply board into the bottom of my 'salvage' box (well, it was only a dollar). I couldn't really understand what had gone wrong at the time - but things like that niggle me, even if it was only a dollar, and after a few weeks of stewing, I was determined to get to the bottom of it.
Thanks to a schematic and a quite detailed review of the board I found, by Peter Vis, I realised that the 3.3 volt regulator is fed straight from the 5 volt regulator's output, rather than directly from the same raw input. So even though the 5 volt regulator was not working properly, if I ran it from the 9 volt supply (which provides around 13-14 volts), then after a random voltage drop... even though it lets through way more than 5 volts, is still safely below 12 volts, and therefore acceptable to the 3.3 volt regulator as an input, giving me a reliable 3.3 volt output and unreliable 5 volt output wobbling around between 8 and 11 volts. This also explains why removing the 5 volt chip rendered the whole board useless.
I am guessing that if I was to now try hooking the board up to the 12 volt supply (which is actually pushing 17-18 volts), then the resulting voltage coming through the dead 5 volt chip would have dropped some, but probably still be higher than 12 volts, and probably fry the 3.3 volt regulator as well. I'm not going to put this theory to the test - yeah... even though it was just a dollar!
Something else I discovered quite by lucky accident, is that the USB plug on these little boards, is a female and is supposed to be an output - also fed from the 5 volt regulator. However, by soldering together the male ends of two USB-A leads (such as from those archaic meeses that nobody wants any more cause they prefer wireless ones), you can take a regulated 5 volt supply from a powerbank, your PC, or your phone charger, put it into the board that way (there is no diode forcing you to use it as an output only), and have a functioning power supply on the breadboard with both 5 and 3.3 volts available. Awesome! (...and very lucky for me, as I had assumed the USB plug was actually an alternate input mechanism anyway - like on my Arduino, and thought it damned inconvenient that I had to make up this lead myself as I couldn't find anywhere that sold Male to Male USB-A leads - that should have rung alarm bells to me, I guess...)
OK - now to look for a new AMS1117 5 volt surface mount regulator. What's the betting they cost more than a dollar!
Footnote - 11/10/2017
I found a seller on eBay that has a packet of 10... for a dollar! Given the potential likelihood of this happening again in the future - I've ordered a pack and will try to repair the faulty board. After all - the chips are only a dollar ;-D
Of course, the first thing I found out is that many of the mains powered DC supplies that come with devices like your broadband modem, cable set-top box, Yamaha electronic keyboard... and so on, are what are called 'unregulated'. This means that while the specs panel on them might say something like 'DC Out : 12v @ 1000mA', what that means is that even if you are drawing 1000mA from it, the unit should still manage to deliver 12 volts. However, to achieve this and avoid the extra component costs of building a regulator into the unit, if you are drawing just a few mA from it, then the unit will generally deliver way over 12 volts, perhaps as much as 50% over - that's 18 volts!!
As my breadboard power supply regulator said it would take an input of up to 12 volts, and I had already used it successfully with a normal PP3 9 volt battery, I felt quite safe connecting it to my 9v @ 1000mA DC supply. Oops - what a 'noob' thing to do. I switched on the breadboard supply, which drew maybe 50mA with nothing except its on board LED and my multimeter connected across it, and shot about 14 volts straight into the regulator - which objected strongly, and let about 10 volts out the other side on what should have been the 5 volt line. Lucky I didn't have anything sensitive plugged into the breadboard!
Now, strangley enough, the 3.3 volt regulator still worked perfectly at the time. So a little while later, having obtained a replacement board (well, it was just a dollar...), I thought that I would remove the surface mounted 5 volt regulator chip - with a view to eventually replacing it - maybe. In the meantime, the absence of that chip would help me identify which board was fully functional, and which could only be trusted at 3.3 volts.
After setting to work with the soldering iron, the chip came off the board easily, and... the 3.3 volt regulator stopped working! Ugh - I threw my hands up in disgust, and threw the power supply board into the bottom of my 'salvage' box (well, it was only a dollar). I couldn't really understand what had gone wrong at the time - but things like that niggle me, even if it was only a dollar, and after a few weeks of stewing, I was determined to get to the bottom of it.
Thanks to a schematic and a quite detailed review of the board I found, by Peter Vis, I realised that the 3.3 volt regulator is fed straight from the 5 volt regulator's output, rather than directly from the same raw input. So even though the 5 volt regulator was not working properly, if I ran it from the 9 volt supply (which provides around 13-14 volts), then after a random voltage drop... even though it lets through way more than 5 volts, is still safely below 12 volts, and therefore acceptable to the 3.3 volt regulator as an input, giving me a reliable 3.3 volt output and unreliable 5 volt output wobbling around between 8 and 11 volts. This also explains why removing the 5 volt chip rendered the whole board useless.
I am guessing that if I was to now try hooking the board up to the 12 volt supply (which is actually pushing 17-18 volts), then the resulting voltage coming through the dead 5 volt chip would have dropped some, but probably still be higher than 12 volts, and probably fry the 3.3 volt regulator as well. I'm not going to put this theory to the test - yeah... even though it was just a dollar!
Something else I discovered quite by lucky accident, is that the USB plug on these little boards, is a female and is supposed to be an output - also fed from the 5 volt regulator. However, by soldering together the male ends of two USB-A leads (such as from those archaic meeses that nobody wants any more cause they prefer wireless ones), you can take a regulated 5 volt supply from a powerbank, your PC, or your phone charger, put it into the board that way (there is no diode forcing you to use it as an output only), and have a functioning power supply on the breadboard with both 5 and 3.3 volts available. Awesome! (...and very lucky for me, as I had assumed the USB plug was actually an alternate input mechanism anyway - like on my Arduino, and thought it damned inconvenient that I had to make up this lead myself as I couldn't find anywhere that sold Male to Male USB-A leads - that should have rung alarm bells to me, I guess...)
OK - now to look for a new AMS1117 5 volt surface mount regulator. What's the betting they cost more than a dollar!
Footnote - 11/10/2017
I found a seller on eBay that has a packet of 10... for a dollar! Given the potential likelihood of this happening again in the future - I've ordered a pack and will try to repair the faulty board. After all - the chips are only a dollar ;-D
Wednesday, 27 September 2017
Bench Supply Regulator - finished (finally)
It's been quite a while since I last published a post, which was partly due to a 3 week 'holiday' back to the UK which left me with a lack of time; partly due to a lack of progress in any of my electronics ventures (due to a lack of time); and partly because I haven't been at all convinced by the reliability of my blog audience stats, and wanted to keep away from blogger for a while to check if it was simply my own activity on any one of 3 different devices, using 2 different browsers, that was giving me 'hits' despite me trying to block it from recording my own activity. Well - after a couple of months away from blogger - I can confirm, depressing though it is... I have absolutely no recent activity at all, so it looks like I am totally wasting my time, and nobody reads this at all. So if nobody reads this, why am I bothering to tell you if you aren't going to read it anyway? Ah well - it is an outlet for my frustration - so I may keep on writing just for the hell of it.
So - on with the post... I have finally completed building my 'Regulator Box' for the bench power supply. The idea was to provide a buffer between unregulated supplies (such as various mains powered wall plug supplies rescued from defunct IT equipment, all of which appear to produce around 50% over-voltage when under little or no load) and the Arduino and breadboard power supplies.
The Arduino can allegedly be fed by up to 20v (though I'm not sure I want to put that to the test), but the breadboard supply will only take a maximum of 12v - as I found to my cost. I plugged one of the aforementioned wall plug supplies into it, that was rated at 12v @ 1000mA, but I later discovered that it was massively NOT putting out 12v as advertised, but actually providing over 17v at the few milliAmps that the PSU on its own was drawing. This very quickly fried the 5v regulator and rendered the PSU useless - but more on that in my next post.
So, what I am planning is for all of my power supplies that plug into the mains and produce vastly different voltages to what is claimed on the specs, as well as the 12v batteries that actually put out anything from 11 to 13v, and the solar panel charge controller (if I ever get solar on the roof) which will be controlling an 18v input under ideal conditions... all of these will plug into my new regulator box. There is an LED display showing the input voltage present (0-30v), and that is fed into the buck converter (which can handle up to 40v). The buck converter is adjusted to provide a regulated 9v output, which is shown by a second LED display, and then made available to my projects via two 2.1mm plugs which can then feed the Arduino and breadboard PSU safely.
I managed to shoe-horn it all into a little project box which is frosted transparent plastic, so with the LED displays pushed up against the case from the inside, they can be read from the outside without the need to cut any holes for them. I drilled a small hole above the adjuster screw on the buck converter, just in case I want to fine tune the output voltage (which does seem to vary slightly based on the input voltage overhead). In terms of construction, I used a hot glue gun to stick the LED displays onto a strip of clear plastic cut from an old tape cartridge box, pushed them right into the bottom of the project box (face down), and then used the hot glue gun to tack the strip in place on the sides. I then did a similar thing with the buck convertor, screwed on the lid, then turned the whole thing upside down so that all the components that were facing downwards, are now at the 'top' of the box. It's not the prettiest thing, but it is functional, and keeps everything contained - I'm happy with it.
So - on with the post... I have finally completed building my 'Regulator Box' for the bench power supply. The idea was to provide a buffer between unregulated supplies (such as various mains powered wall plug supplies rescued from defunct IT equipment, all of which appear to produce around 50% over-voltage when under little or no load) and the Arduino and breadboard power supplies.
The Arduino can allegedly be fed by up to 20v (though I'm not sure I want to put that to the test), but the breadboard supply will only take a maximum of 12v - as I found to my cost. I plugged one of the aforementioned wall plug supplies into it, that was rated at 12v @ 1000mA, but I later discovered that it was massively NOT putting out 12v as advertised, but actually providing over 17v at the few milliAmps that the PSU on its own was drawing. This very quickly fried the 5v regulator and rendered the PSU useless - but more on that in my next post.
So, what I am planning is for all of my power supplies that plug into the mains and produce vastly different voltages to what is claimed on the specs, as well as the 12v batteries that actually put out anything from 11 to 13v, and the solar panel charge controller (if I ever get solar on the roof) which will be controlling an 18v input under ideal conditions... all of these will plug into my new regulator box. There is an LED display showing the input voltage present (0-30v), and that is fed into the buck converter (which can handle up to 40v). The buck converter is adjusted to provide a regulated 9v output, which is shown by a second LED display, and then made available to my projects via two 2.1mm plugs which can then feed the Arduino and breadboard PSU safely.
I managed to shoe-horn it all into a little project box which is frosted transparent plastic, so with the LED displays pushed up against the case from the inside, they can be read from the outside without the need to cut any holes for them. I drilled a small hole above the adjuster screw on the buck converter, just in case I want to fine tune the output voltage (which does seem to vary slightly based on the input voltage overhead). In terms of construction, I used a hot glue gun to stick the LED displays onto a strip of clear plastic cut from an old tape cartridge box, pushed them right into the bottom of the project box (face down), and then used the hot glue gun to tack the strip in place on the sides. I then did a similar thing with the buck convertor, screwed on the lid, then turned the whole thing upside down so that all the components that were facing downwards, are now at the 'top' of the box. It's not the prettiest thing, but it is functional, and keeps everything contained - I'm happy with it.
Tuesday, 25 July 2017
Photography Flash Trigger - Pt 2

Last night, I did a bit more work on the Flash Trigger project. The first thing was to remove the testing printouts to the Serial Monitor, and replace it with the LCD, and then I mounted the receiver and LED on either side of a bit of card to try it out as a reflective receiver. That was much easier to keep lined up with the dripping tap.
I've modified the loop() logic so that when the beam is interrupted, this triggers a quick beep, puts a message on the LCD, and starts a 3 second countdown. During the countdown period, the LED (on pin 13) will still flash to indicate when the beam is broken, but nothing else will happen. After 3 seconds, it all resets, and the trigger's ready to go again. I also added a counter to keep track of how many times the trigger is.... well, triggered. The latest version of the code looks like this...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | #include <NewTone.h> #include <IRremote.h> #include <LiquidCrystal_I2C.h> #define PIN_IR 3 // Documentary value only - Pin 3 (OC2B) is hard-coded in the library. #define PIN_DETECT 2 #define PIN_STATUS 13 #define PIN_TONE 9 // Instantiate objects IRsend irsend; LiquidCrystal_I2C lcd(0x3F,20,4); // set up global variables int triggered = 0; long trigMs = millis(); int trigCount = 0; void setup() { // Set pins as IN or OUT pinMode(PIN_DETECT, INPUT); pinMode(PIN_STATUS, OUTPUT); pinMode(PIN_TONE, OUTPUT); // Put prompt on display (Coordinates = col 0-19, row 0-3) lcd.begin(); lcd.setCursor(0,0); lcd.print("IR Beamer waiting..."); // Start the IR LED sending irsend.enableIROut(38); irsend.mark(0); } void loop() { // Check beam and update LED in real time int beamState = !digitalRead(PIN_DETECT); digitalWrite(PIN_STATUS, beamState); // If newly triggered... if(beamState == 1 && triggered == 0) { // set flag and note the time triggered = 1; trigMs = millis(); trigCount++; // beep // NewTone(PIN_TONE,750,250); // The beep gets quite annoying // update LCD lcd.setCursor(10,0); lcd.print("TRIGGERED!"); lcd.setCursor(1,1); lcd.print("(Counter="); lcd.print(trigCount); lcd.print(")"); lcd.setCursor(1,3); lcd.print("resets in 3 seconds"); } // Once triggered... // If 3 seconds have passed, then reset if(triggered == 1 && (millis() > (trigMs + 3000))) { lcd.setCursor(10,0); lcd.print("waiting..."); lcd.setCursor(1,3); lcd.print(" "); triggered = 0; } // If 2 seconds have passed, update countdown else if(triggered == 1 && (millis() > (trigMs + 2000))) { lcd.setCursor(11,3); lcd.print("1"); lcd.setCursor(19,3); lcd.print(" "); } // If 1 second has passed, update countdown else if(triggered == 1 && (millis() > (trigMs + 1000))) { lcd.setCursor(11,3); lcd.print("2"); } } |
I checked it out with the tap, and it was working pretty well, as long as it was within about 3-6" of the drips. When IR remotes work from the sofa to the TV on the other side of the room, I was quite surprised that the range on my little contraption is only a few inches, but it is good enough for the particular job I have in mind.
The next step is to link the trigger action to an actual external device via a photocoupler - and then finally, introduce a delay.
By the way, the header pins that I ordered turned up at the end of last week, and the supplier also sent me a replacement set in case the originals had gone missing, and they turned up this morning. Also in the post this morning was part 1 of my regulated power supply project - the buck converter - which has arrived 2 days before the estimated timeframe! I must connect that up to some of my supplies and give it a bit of a test before I leave feedback for the seller.
With all these envelopes turning up, I felt a little like Julian Ilett and his " It's Postbag" videos on youtube. Speaking of which, I was a little concerned when I found he has done a video about 'fake' LM2596 boards exactly like the one I ordered from ebay... thankfully, it turned out that what he was describing was sellers claiming to be selling the High Voltage (HV) version of the LM2596 which is rated at up to 60VDC input, but only putting the standard LM2596 (relabelled to look like the HV version) on the board, which is rated to 40VDC, or putting a fake 65V capacitor on the input side of the circuit (looked like the standard 50V cap with overprinting) - so the boards worked OK up to around 40-45V as per the design of the standard components, but then started behaving very strangely, and sometimes smoking gently, at anything higher. Hopefully, as I have bought the standard 40V model, with the intention that it will never experience inputs above around 20VDC, there should not be a problem...
Sunday, 16 July 2017
Photography Flash Trigger - Pt 1
Unfortunately, despite the seller's promises of a very quick ETA for the header pins I ordered at the beginning of the week, which were supposed to arrive Thursday or Friday, they have sadly failed to deliver - quite literally.
So this weekend's I2C LCD interface cable project was sidelined and I decided to do a little testing towards my photography project instead. The idea of the project is to have an optical beam of some sort, either IR or visible light, which can act as a trigger for my camera flash when the beam is broken. The aim being to be able to accurately capture water droplets as they hit a surface and break apart or bounce, etc.
To account for how far the drop needs to fall, I also want to have a variable resistor on an analogue input, that can be used to introduce a delay between when the beam is broken, and when the trigger occurs.With 1024 points on the analogue input scale, I figure that each point can be a millisecond and that will give me up to a second's worth of delay adjustment (or a little over). The range I anticipate needing would most likely be no more than half a second, so I could possibly even go for 2 points per millisecond.
Of course the first step is to get the beam part working, and that's what I experimented with today. I used Ken Shirrif's IRremote library to get the basic functionality, as I found a post on his blog with sample code for a basic beam-break sketch using an IR LED and VS1838B receiver. I know there is a newer library available, but it comes with warnings that it is not backwards compatible in some areas, and when I tried it with Ken's code - I got errors that I couldn't fathom so decided to just use his library instead.
A word of warning here - there are some conflicts between his library, and the Arduino RobotRemote library that comes as standard with the IDE install. You will need to move or delete the RobotRemote library to use IRremote without errors.
There are 2 parts to the sketch - the first part is to set the IR LED constantly sending out a beam. IR LEDs can draw a lot of power, and also generate heat - so the standard practice is to use a 50/50 pulse width modulation (PWM) at 38KHz. All modern IR remote controls conform to this standard, though some older ones use 56KHz, but for the same reason. The IRremote library takes care of this for you, so you don't need to work out all the PWM parameters and timings.
In his sample code, Ken has line 3 above set to PIN 3. I wonder if this is more documentary than actual requirement, as when I tried to use pin 5, it would not work. However, I plugged the LED into pin 3 and it worked despite my sketch having PIN_IR set to 5.
Line 4 instantiates an IRsend object, and calls it irsend.
Line 7 and 8 are in the setup() routine, so are only done once. Line 7 sets the IR PWM frequency to 38 (KHz), and line 8 sends a 'mark' - which seems to be the IR equivalent of setting a digital output pin high. The parameter on the mark action is a duration. IR remotes work by sending on and off sequences, a bit like morse code, but with varying length ons and offs. The duration parameter defines how many milliseconds the 'on' should last. 0 indicates that it will stay on indefinitely - which is just what I need for my beam.
The second part of the code concerns the receiver which senses the beam, and recognises when it is broken.
The detector pin is connected to pin 2, and declared as an INPUT
Pin 13 (the on-board LED) is set as an OUTPUT and used to indicate the status. It will flash on when the beam is broken. I also added monitoring via the Serial Monitor, and set a buzzer to beep, but for now, this is the pure IR code only.
Line 13 in the loop() routine is the key here - it checks the value on the detector pin (2) and uses that to control the on-board LED. Under normal circumstances, the detector will be receiving a constant signal from the IR LED, but we don't want the on-board LED on all the time, so we invert the value, by preceding it with '!' That way, the LED flashes on only when the beam is broken.
One thing I found with this sketch, is that the trigger actually occurs not at the point in time that the beam is interrupted, but at the point the beam is re-instated. I could place my hand between the IR LED and receiver, and nothing happened... until I took my hand away and the beam was able to hit the sensor again. For my application, I don't foresee this being a huge problem, but in other applications, it could be an issue.
The two extracts above were combined together and gave me the basic sketch, but I felt that an audible feedback would be useful, so I added a tone() command in the loop() routine. Uh-oh, now my sketch will no longer compile! Something about multiple definitions of vector7..???
I had no idea what this meant, but it seems many people have experienced it. It is something to do with the on-board timers inside the ATmega328 chip, and how they are used in people's libraries. There are only so many timers, and a lot of libraries - so it is inevitable that eventually, you will come across 2 libraries you want to use together, that are trying to use the same timer for different things. In my case, I think it was the timer being used to control PWM for the tone() command conflicting with PWM for the IR LED. Luckily, I was able to find an alternate tone library (NewTone.h) that uses a different timer, and this got rid of my conflict.
So here is my complete code with Serial Monitor and bleeper included.
I set it all up on the breadboard, and it worked OK, but I really wanted the LED and sensor on a longish lead so that the Uno and power, etc, can all be far away from any water splashing. So, I've now wired them onto a half meter length of 6 core cable, with two cores going to the LED and three to the sensor, and terminated them onto a new little DIY break-out board for convenient connection to the breadboard.
However, having got this far, I am not convinced that the IR LED and Receiver is going to be the right solution. It does not seem to react very quickly at all... I can easily pass my finger between the LED and sensor and it not trigger the beep or flash the LED on pin 13. I am also not convinced that a water droplet will provide enough of a barrier to the IR light to actually interrupt the beam in the first place.
Supplemental - Well, what do you know? It actually works, well, to a degree anyway... The somewhat shaky hand held alignment of the LED and Receiver was introducing a lot of false triggers, but when I could hold them still enough relative to each other on either side of a dripping tap, I was rewarded by a fairly consistent beep... beep... beep! This means I would need to jury-rig some kind of frame to hold the two devices in alignment to each other, and also be able to place that securely in position around the dripping tap. However, this is just the first of a few alternative ideas I want to try, the next being a reflective beam contact, as opposed to a beam break - so I will arrange the sensor and LED adjacent to each other both facing in the same direction, but separated by a barrier, the idea being that as the water drop passes, it reflects the IR beam back to the sensor. It should be easier to construct a rig for this arrangement - if the concept works.
By the way - I had a surprise package arrive from China today - the replacement MB102 PSU whose regulator became deregulated.
So this weekend's I2C LCD interface cable project was sidelined and I decided to do a little testing towards my photography project instead. The idea of the project is to have an optical beam of some sort, either IR or visible light, which can act as a trigger for my camera flash when the beam is broken. The aim being to be able to accurately capture water droplets as they hit a surface and break apart or bounce, etc.
To account for how far the drop needs to fall, I also want to have a variable resistor on an analogue input, that can be used to introduce a delay between when the beam is broken, and when the trigger occurs.With 1024 points on the analogue input scale, I figure that each point can be a millisecond and that will give me up to a second's worth of delay adjustment (or a little over). The range I anticipate needing would most likely be no more than half a second, so I could possibly even go for 2 points per millisecond.
Of course the first step is to get the beam part working, and that's what I experimented with today. I used Ken Shirrif's IRremote library to get the basic functionality, as I found a post on his blog with sample code for a basic beam-break sketch using an IR LED and VS1838B receiver. I know there is a newer library available, but it comes with warnings that it is not backwards compatible in some areas, and when I tried it with Ken's code - I got errors that I couldn't fathom so decided to just use his library instead.
A word of warning here - there are some conflicts between his library, and the Arduino RobotRemote library that comes as standard with the IDE install. You will need to move or delete the RobotRemote library to use IRremote without errors.
There are 2 parts to the sketch - the first part is to set the IR LED constantly sending out a beam. IR LEDs can draw a lot of power, and also generate heat - so the standard practice is to use a 50/50 pulse width modulation (PWM) at 38KHz. All modern IR remote controls conform to this standard, though some older ones use 56KHz, but for the same reason. The IRremote library takes care of this for you, so you don't need to work out all the PWM parameters and timings.
1 2 3 4 5 6 7 8 9 | #include <IRremote.h> #define PIN_IR 5 // Only seems to work when connected to pin 3 regardless of this setting IRsend irsend; void setup() { irsend.enableIROut(38); irsend.mark(0); } |
In his sample code, Ken has line 3 above set to PIN 3. I wonder if this is more documentary than actual requirement, as when I tried to use pin 5, it would not work. However, I plugged the LED into pin 3 and it worked despite my sketch having PIN_IR set to 5.
Line 4 instantiates an IRsend object, and calls it irsend.
Line 7 and 8 are in the setup() routine, so are only done once. Line 7 sets the IR PWM frequency to 38 (KHz), and line 8 sends a 'mark' - which seems to be the IR equivalent of setting a digital output pin high. The parameter on the mark action is a duration. IR remotes work by sending on and off sequences, a bit like morse code, but with varying length ons and offs. The duration parameter defines how many milliseconds the 'on' should last. 0 indicates that it will stay on indefinitely - which is just what I need for my beam.
The second part of the code concerns the receiver which senses the beam, and recognises when it is broken.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #include <IRremote.h> #define PIN_DETECT 2 #define PIN_STATUS 13 IRsend irsend; void setup() { pinMode(PIN_DETECT, INPUT); pinMode(PIN_STATUS, OUTPUT); } void loop() { digitalWrite(PIN_STATUS, !digitalRead(PIN_DETECT)); } |
The detector pin is connected to pin 2, and declared as an INPUT
Pin 13 (the on-board LED) is set as an OUTPUT and used to indicate the status. It will flash on when the beam is broken. I also added monitoring via the Serial Monitor, and set a buzzer to beep, but for now, this is the pure IR code only.
Line 13 in the loop() routine is the key here - it checks the value on the detector pin (2) and uses that to control the on-board LED. Under normal circumstances, the detector will be receiving a constant signal from the IR LED, but we don't want the on-board LED on all the time, so we invert the value, by preceding it with '!' That way, the LED flashes on only when the beam is broken.
One thing I found with this sketch, is that the trigger actually occurs not at the point in time that the beam is interrupted, but at the point the beam is re-instated. I could place my hand between the IR LED and receiver, and nothing happened... until I took my hand away and the beam was able to hit the sensor again. For my application, I don't foresee this being a huge problem, but in other applications, it could be an issue.
The two extracts above were combined together and gave me the basic sketch, but I felt that an audible feedback would be useful, so I added a tone() command in the loop() routine. Uh-oh, now my sketch will no longer compile! Something about multiple definitions of vector7..???
I had no idea what this meant, but it seems many people have experienced it. It is something to do with the on-board timers inside the ATmega328 chip, and how they are used in people's libraries. There are only so many timers, and a lot of libraries - so it is inevitable that eventually, you will come across 2 libraries you want to use together, that are trying to use the same timer for different things. In my case, I think it was the timer being used to control PWM for the tone() command conflicting with PWM for the IR LED. Luckily, I was able to find an alternate tone library (NewTone.h) that uses a different timer, and this got rid of my conflict.
So here is my complete code with Serial Monitor and bleeper included.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #include <NewTone.h> #include <IRremote.h> #define PIN_IR 5 // Only seems to work when connected to pin 3 regardless of this setting #define PIN_DETECT 2 #define PIN_STATUS 13 #define PIN_TONE 9 IRsend irsend; void setup() { pinMode(PIN_DETECT, INPUT); pinMode(PIN_STATUS, OUTPUT); pinMode(PIN_TONE, OUTPUT); irsend.enableIROut(38); irsend.mark(0); Serial.begin(9600); } void loop() { int beamState = !digitalRead(PIN_DETECT); digitalWrite(PIN_STATUS, beamState); Serial.println(beamState); if(beamState == 1) { NewTone(PIN_TONE,750,250); } } |
I set it all up on the breadboard, and it worked OK, but I really wanted the LED and sensor on a longish lead so that the Uno and power, etc, can all be far away from any water splashing. So, I've now wired them onto a half meter length of 6 core cable, with two cores going to the LED and three to the sensor, and terminated them onto a new little DIY break-out board for convenient connection to the breadboard.
However, having got this far, I am not convinced that the IR LED and Receiver is going to be the right solution. It does not seem to react very quickly at all... I can easily pass my finger between the LED and sensor and it not trigger the beep or flash the LED on pin 13. I am also not convinced that a water droplet will provide enough of a barrier to the IR light to actually interrupt the beam in the first place.
Supplemental - Well, what do you know? It actually works, well, to a degree anyway... The somewhat shaky hand held alignment of the LED and Receiver was introducing a lot of false triggers, but when I could hold them still enough relative to each other on either side of a dripping tap, I was rewarded by a fairly consistent beep... beep... beep! This means I would need to jury-rig some kind of frame to hold the two devices in alignment to each other, and also be able to place that securely in position around the dripping tap. However, this is just the first of a few alternative ideas I want to try, the next being a reflective beam contact, as opposed to a beam break - so I will arrange the sensor and LED adjacent to each other both facing in the same direction, but separated by a barrier, the idea being that as the water drop passes, it reflects the IR beam back to the sensor. It should be easier to construct a rig for this arrangement - if the concept works.
By the way - I had a surprise package arrive from China today - the replacement MB102 PSU whose regulator became deregulated.
Labels:
Arduino,
electronics,
IR LED,
IR Sensor,
NewTone.h,
Photography,
PWM,
VS1838B
Monday, 10 July 2017
Shopping list 2
Last night, I ordered a few more items from some of eBay's abundant "Free postage, but two month wait time" sellers in China.
As noted in a previous post, I discovered that pretty much all of my my power supplies, are unregulated, and deliver about 40-50% over-voltage when under no, or light loading. The same will be true if I ever get around to using a solar panel to charge my 12V batteries. So I've decided to build a simple regulator box, that can take anything up to 20V (my biggest mains power supply units are 12V - putting out around 18V, and a 12V solar panel can also get up to around 18-20V under ideal conditions.), and put out a regulated 9 or 12V, which can then in turn be safely put through either the Arduino Uno or MB102 PSU on-board regulators, to provide 5 or 3.3V to my circuitry.
I've found a 'buck' converter based on an adjustable output LM2596 regulator, for just $1.25, that takes anything from 4.5 up to 40V input, has a fully adjustable output ranging from 1.5 to 37V (so appears to require an overhead of 3V), and can handle up to 3A of current drawn through it - but I'll hopefully never need anything like that amount. This will be the core of my regulator box.
I found some 3-30V 3-digit LED voltmeters, for $1.20 each, and I am going to wire one of those on each side of my regulator, to monitor the input and output voltages.
I will put a 2.1mm jack on the input side (salvaged from one of many old bits of hardware in my 'junk' box at work), to take power from the mains DC units, but at the moment, I'm not sure what to do for the connections on the output side. Obviously, I want the regulated voltage to feed the Uno, but as the Uno has a limited potential for current, it would be nice to also be able to tap directly off the regulated supply for higher powered devices, such as fans and motors. So maybe I'll have 2 output options - a simple 2.1mm plug that can connect to the Uno and MB102 for low power control circuits, and then the option to tap directly into the regulated voltage at higher amperage if required. Just not sure what kind of connection to use for this - perhaps some form of PCB mounted pin connector that I can then connect to the breadboard using DuPont cables..? It would be nice to mount all this in a little jiffy project box, and then mount it onto a board with the Uno, LCD, and breadboard all permanently mounted as a mini workbench.
The next item I've purchased is a Real Time Clock (RTC) module, based on the DS1302 chip. I've read a few warnings saying they aren't the most accurate of devices, but to be honest - I don't need something that is accurate to less than a microsecond over 10 years... I just get fed up having to keep type in the seed time and date for any time-based projects while I am testing them. So for $1.00, even if it loses a few seconds a day, it will do for my needs... maybe I can get some sort of wireless connection next time, that will allow me to reset the clock time from my PC or the internet once in a while.
My final purchase, was a bundle of header pin strips. I got one set with my Uno clone, but have already used about half of them on my little breakout boards and for other testing, and that's without putting any on the Uno itself. I've got a bundle of ten 40 pin strips - should keep me going for a while.
So, now I just need to sit back and see how long they take to arrive. I placed all 4 orders last night 9th July, and 3 of the 4 claim to have 'sent' the items already, two with an ETA of 'before August 8th' (WOW - just ONE month!) and one (sadly, the regulator itself) not until September 1st. I guess that means they have been packed and thrown into a 40ft shipping container on a dock somewhere, and when the container is full, it will be loaded onto the next cargo carrier coming our way...
The final item (RTC) has not yet been sent, though ironically, its ETA was the earliest at August 3rd!
I'll update this post as and when the items arrive.
11/07 - I got notified overnight that the RTC has now also been despatched, with an ETA of August 2nd. Today, I also made one more purchase, this time of some 1x4 female header pin PCB connectors. Thinking ahead to mounting all my gear on a little workbench, I want to utilise the extra bank of optional connection points for power and SDA/SCL, and build a custom semi-permanent I2C connection cable. I could have ordered a pack of 10 of them from another Chinese supplier for $1, and waited till September, or pay $2 for the same pack of 10 and have them on Friday... I'm getting a little fed up with waiting for China's free "Economy International Post" option, so I paid the extra dollar and will be able to put up a post showing my upgrade at the weekend hopefully ;-)
25/07 - Ironically, the LM2596 regulator - the item with the latest ETA - arrived today, two days ahead of the start of the potential delivery period, and a full 5 weeks ahead of their final ETA date!
As noted in a previous post, I discovered that pretty much all of my my power supplies, are unregulated, and deliver about 40-50% over-voltage when under no, or light loading. The same will be true if I ever get around to using a solar panel to charge my 12V batteries. So I've decided to build a simple regulator box, that can take anything up to 20V (my biggest mains power supply units are 12V - putting out around 18V, and a 12V solar panel can also get up to around 18-20V under ideal conditions.), and put out a regulated 9 or 12V, which can then in turn be safely put through either the Arduino Uno or MB102 PSU on-board regulators, to provide 5 or 3.3V to my circuitry.
I've found a 'buck' converter based on an adjustable output LM2596 regulator, for just $1.25, that takes anything from 4.5 up to 40V input, has a fully adjustable output ranging from 1.5 to 37V (so appears to require an overhead of 3V), and can handle up to 3A of current drawn through it - but I'll hopefully never need anything like that amount. This will be the core of my regulator box.
I found some 3-30V 3-digit LED voltmeters, for $1.20 each, and I am going to wire one of those on each side of my regulator, to monitor the input and output voltages.
I will put a 2.1mm jack on the input side (salvaged from one of many old bits of hardware in my 'junk' box at work), to take power from the mains DC units, but at the moment, I'm not sure what to do for the connections on the output side. Obviously, I want the regulated voltage to feed the Uno, but as the Uno has a limited potential for current, it would be nice to also be able to tap directly off the regulated supply for higher powered devices, such as fans and motors. So maybe I'll have 2 output options - a simple 2.1mm plug that can connect to the Uno and MB102 for low power control circuits, and then the option to tap directly into the regulated voltage at higher amperage if required. Just not sure what kind of connection to use for this - perhaps some form of PCB mounted pin connector that I can then connect to the breadboard using DuPont cables..? It would be nice to mount all this in a little jiffy project box, and then mount it onto a board with the Uno, LCD, and breadboard all permanently mounted as a mini workbench.
The next item I've purchased is a Real Time Clock (RTC) module, based on the DS1302 chip. I've read a few warnings saying they aren't the most accurate of devices, but to be honest - I don't need something that is accurate to less than a microsecond over 10 years... I just get fed up having to keep type in the seed time and date for any time-based projects while I am testing them. So for $1.00, even if it loses a few seconds a day, it will do for my needs... maybe I can get some sort of wireless connection next time, that will allow me to reset the clock time from my PC or the internet once in a while.
My final purchase, was a bundle of header pin strips. I got one set with my Uno clone, but have already used about half of them on my little breakout boards and for other testing, and that's without putting any on the Uno itself. I've got a bundle of ten 40 pin strips - should keep me going for a while.
So, now I just need to sit back and see how long they take to arrive. I placed all 4 orders last night 9th July, and 3 of the 4 claim to have 'sent' the items already, two with an ETA of 'before August 8th' (WOW - just ONE month!) and one (sadly, the regulator itself) not until September 1st. I guess that means they have been packed and thrown into a 40ft shipping container on a dock somewhere, and when the container is full, it will be loaded onto the next cargo carrier coming our way...
The final item (RTC) has not yet been sent, though ironically, its ETA was the earliest at August 3rd!
I'll update this post as and when the items arrive.
11/07 - I got notified overnight that the RTC has now also been despatched, with an ETA of August 2nd. Today, I also made one more purchase, this time of some 1x4 female header pin PCB connectors. Thinking ahead to mounting all my gear on a little workbench, I want to utilise the extra bank of optional connection points for power and SDA/SCL, and build a custom semi-permanent I2C connection cable. I could have ordered a pack of 10 of them from another Chinese supplier for $1, and waited till September, or pay $2 for the same pack of 10 and have them on Friday... I'm getting a little fed up with waiting for China's free "Economy International Post" option, so I paid the extra dollar and will be able to put up a post showing my upgrade at the weekend hopefully ;-)
25/07 - Ironically, the LM2596 regulator - the item with the latest ETA - arrived today, two days ahead of the start of the potential delivery period, and a full 5 weeks ahead of their final ETA date!
Labels:
Buck Converter,
DS1302,
eBay,
electronics,
LM2596,
RTC
Testing tone();
At the weekend, I quickly cobbled together another of my little break-out boards, this time for a piezo crystal transducer (or a buzzer to you and me).
One thing this taught me is that although we all call these things buzzers - actually, they are just 'clickers'. If you apply voltage to it, it just goes click. The tone comes from applying and disconnecting power 1000 times a second, to get a 1KHz tone for example. A real ''buzzer' has components and circuitry built into it, so that all you need to do is apply power, and you get a nice tone generated.
Anyway - I digress... That was not really the point of this post. I found out something else, which wasn't really immediately evident to me from the Arduino Reference manual, and even looking at it again with hindsight - I still didn't find anything about it...
To generate a tone on an Arduino, simply connect a 'clicker' thingy (I'm just going to call it a buzzer) to an output enabled pin and GND (NB - the buzzers are polarity sensitive, and have the positive pin marked on the casing, or indicated with a red lead), and then there is a nice easy tone command that does the work of generating the square wave for you. Typically, the code looks something like this...
// start sending the tone of toneFrequency Hz to the device on buzzerPin
tone(buzzerPin, toneFrequency);
// keep doing it for the period toneDuration milliseconds
delay(toneDuration);
// at the end of the toneDuration delay, stop sending the tone
noTone(buzzerPin);
I was using this code in a little sketch to make a hospital heartbeat monitor type 'beep', and also flashing the LED in time with the beep. It all worked fine, and I should really have left well alone at this point (if it ain't broke, don't fix it!)
But then, I found an alternate version of the tone command, that includes the duration as a third parameter. Why would anyone go to the lengths of typing 3 lines of code, when one will do..? So I tried it...
// Same function, but all in one command
tone(buzzerPin, toneFrequency, toneDuration);
// No need for the delay() or noTone() commands!
It worked! Well, at first glance, it seemed to have worked, but then I noticed something odd - my LED was no longer flashing. Actually, it was, but only for the briefest of moments, and unless you covered up the adjacent power LED (yeah - ALL the LEDs are clustered together on my clone - and very bright - it's a bit of a pain sometimes) you really wouldn't notice it.
I wondered about the potential for the buzzer to be drawing too much voltage and not leaving enough for the LED, so I disconnected the the buzzer. The LED was still only giving the faintest of flickers. I wondered if the 100ms period was too quick, though my gut was already saying "of course it's not". I went back to basics and installed Blink, and changed it to 100ms. Yes it was fast, but the LED lit up properly. So I went back to my sketch and changed the toneDuration to 5000 millis. No change in the LED, but something else odd was now happening - the normal round-trip duration of the loop() section of my sketch was about 3 seconds, including a 1 second delay at the end. I was expecting my tone to now run for 5 seconds, followed by 1 second pause, but it was running constantly.
Then, the penny dropped - including the toneDuration as a parameter on the tone command, appears to switch it to background operation. That means that the sketch starts generating the tone, and can carry on with the rest of the lines of code while the tone is being sounded. So, what was happening is that my LED was switching on, staying on for probably just a few microseconds while the tone command was being evaluated, and then switched straight off again. furthermore, if the toneDuaration value exceeds the time it takes for the rest of the code in loop() to run through - including any delay() commands, then the 'next' tone starts sounding before the first has finished, so it sounds like it is going constantly.
So - just be a little bit careful with the two flavours of the tone command - they are not the same beast at all, and make sure you know whether you want the duration of your tone to play an integral part in the progression of your code, or if it can be set off and left to run independently while your code goes and does something else... If you choose the latter option, make sure there is room in your loop() code for the tone to finish before the loop does.
One thing this taught me is that although we all call these things buzzers - actually, they are just 'clickers'. If you apply voltage to it, it just goes click. The tone comes from applying and disconnecting power 1000 times a second, to get a 1KHz tone for example. A real ''buzzer' has components and circuitry built into it, so that all you need to do is apply power, and you get a nice tone generated.
Anyway - I digress... That was not really the point of this post. I found out something else, which wasn't really immediately evident to me from the Arduino Reference manual, and even looking at it again with hindsight - I still didn't find anything about it...
To generate a tone on an Arduino, simply connect a 'clicker' thingy (I'm just going to call it a buzzer) to an output enabled pin and GND (NB - the buzzers are polarity sensitive, and have the positive pin marked on the casing, or indicated with a red lead), and then there is a nice easy tone command that does the work of generating the square wave for you. Typically, the code looks something like this...
// start sending the tone of toneFrequency Hz to the device on buzzerPin
tone(buzzerPin, toneFrequency);
// keep doing it for the period toneDuration milliseconds
delay(toneDuration);
// at the end of the toneDuration delay, stop sending the tone
noTone(buzzerPin);
I was using this code in a little sketch to make a hospital heartbeat monitor type 'beep', and also flashing the LED in time with the beep. It all worked fine, and I should really have left well alone at this point (if it ain't broke, don't fix it!)
But then, I found an alternate version of the tone command, that includes the duration as a third parameter. Why would anyone go to the lengths of typing 3 lines of code, when one will do..? So I tried it...
// Same function, but all in one command
tone(buzzerPin, toneFrequency, toneDuration);
// No need for the delay() or noTone() commands!
It worked! Well, at first glance, it seemed to have worked, but then I noticed something odd - my LED was no longer flashing. Actually, it was, but only for the briefest of moments, and unless you covered up the adjacent power LED (yeah - ALL the LEDs are clustered together on my clone - and very bright - it's a bit of a pain sometimes) you really wouldn't notice it.
I wondered about the potential for the buzzer to be drawing too much voltage and not leaving enough for the LED, so I disconnected the the buzzer. The LED was still only giving the faintest of flickers. I wondered if the 100ms period was too quick, though my gut was already saying "of course it's not". I went back to basics and installed Blink, and changed it to 100ms. Yes it was fast, but the LED lit up properly. So I went back to my sketch and changed the toneDuration to 5000 millis. No change in the LED, but something else odd was now happening - the normal round-trip duration of the loop() section of my sketch was about 3 seconds, including a 1 second delay at the end. I was expecting my tone to now run for 5 seconds, followed by 1 second pause, but it was running constantly.
Then, the penny dropped - including the toneDuration as a parameter on the tone command, appears to switch it to background operation. That means that the sketch starts generating the tone, and can carry on with the rest of the lines of code while the tone is being sounded. So, what was happening is that my LED was switching on, staying on for probably just a few microseconds while the tone command was being evaluated, and then switched straight off again. furthermore, if the toneDuaration value exceeds the time it takes for the rest of the code in loop() to run through - including any delay() commands, then the 'next' tone starts sounding before the first has finished, so it sounds like it is going constantly.
So - just be a little bit careful with the two flavours of the tone command - they are not the same beast at all, and make sure you know whether you want the duration of your tone to play an integral part in the progression of your code, or if it can be set off and left to run independently while your code goes and does something else... If you choose the latter option, make sure there is room in your loop() code for the tone to finish before the loop does.
Monday, 3 July 2017
A little DIY, an AHA and a D'Oh!

I got the soldering iron out at the weekend, and what do you know, I managed to fix my LM35 temperature sensor after all. I used a small bit of Vero stripboard and soldered the outer two legs in place on tracks 1 and 3, with the body laying down almost flat on the board. Then I got a short bit of bare jumper wire bent at a right angle, and soldered it to the middle track while the upright part was leaning against the base. The soldering of that upright to the body of the chip was the tricky part as there wasn't much room between the other two pins to manoeuvre the tip of my soldering iron, or for a clumsy blob of solder that might short the pins out. Thankfully, there was just enough exposed bare metal left over from the broken leg for a drop of solder to actually take and make the connection. A 3 pin section of header pins completed the job - and Wahay! I have a working sensor again.
My soldering isn't too pretty, but it got the job done. The only thing I wish I could have done was solder on the underside, so that I could write pinout information on the bare side of the board and have it visible when plugged into the breadboard, but I couldn't figure how to solder the header pins that way. With hindsight, maybe what I should have done was push the black plastic clip right to the end of the pins, and then feed them through from above for soldering. After soldering, take the black clip off the top and slide it back on the underside again.

Of course, to test the sensor, I needed a 5V supply on the breadboard, and remember - it appears that the 5V regulator on my MB-102 PSU is blown. However, the original board that the LM35 was on had its own 5V regulator. So after my soldering success, I decided to build myself a little regulator board too. The regulator is an L78L05, and it had a 22µF capacitor across the Vin and GND pins. It seemed a simple little project, and with just two components and 3 header pins, it was actually quicker than repairing the LM35.
To test it all, I connected a 12V battery to the PSU. The 5V output was actually putting out nearly 9V, so I put that through my new DIY regulator and that gave a nice steady 4.98V. I connected that to my LM35 and got an output of around 180mV, which went up and down as I breathed on the sensor (it's pretty cold here in Sydney at the moment!), so I was quite happy that my DIY repair appears to have worked. Note the mV value here - it should have triggered some thought process here - but I missed it... read on.
Later in the evening, I loaded up my Min/Max temperature sketch, and connected the sensor to the Arduino - it certainly seemed to be working, but was giving readings of a balmy 23-24C while I was sitting there feeling my toes going numb. I tried changing the reference voltage between 5V and 1.1V, and tried running from a battery rather than USB, but each change seemed to be giving me all kinds of different readings. I checked the datasheet again, and then had one of those blinding flashes of the bleedin' obvious - a real slap on the forehead "d'oh!" moment...
The sensor generates 10mv per degree C, but nowhere does it say that 0V = 0C. The chip is supposed to have a range starting at -55C... so of course - that must be the 0V point. This means that even at freezing point, the output pin should be reading 550mV. I had assumed that 0C would generate 0V and somehow -55C would generate a -ve voltage! Well it made sense at the time, but looking back - how stupid was I?? (Hah - remember this statement)
So with this new 'understanding', I looked at my calculations and figured that all I needed to do was offset my calculations by the 55 negative degrees (but by subtracting 5.5 from the final answer?)... Yeah -OK, it was late at night, and the 55 degrees got all muddled with the factor of 10 (mV per degree) in my head, and suddenly, my calculations were coming up with temperatures almost exactly matching the digital thermometer I was using as a reference.
1 2 | // Calculation for analogReference(INTERNAL) at 1.1v at .1C resolution float celsius=((1.1 * analogVal * 100.0) / 1024.0) - 5.5; |
BUT this was all completely wrong and purely coincidental, and having revisited it yet again this evening, I'm still not convinced I am understanding either the calculations or even operation of the sensor. A fact I had previously missed entirely is that there is more than one way to wire up the LM35 - in fact there are 14 different wiring examples in the datasheet with pullup resistors, diodes, and all manner of schemes - each of which makes it operate differently and respond to a different range of temperatures. I have been using the most basic +5V, GND, and signal back to the Arduino. Apparently, this gives a measured range of 2C to 150C - so there are no 55 degrees of negativity to account for after all. That means my adjustment of -5.5, while giving me good results, is simply a fudge factor, and there is still an inaccuracy that I need to track down. However, it does mean that the 180mV I saw while testing my DIY repair out in the garage, makes more sense - it probably would have been around 18C out there. So knowing the range I have, I now need to know if 2C = 0mv or 20mV...
I think the next stage in my testing is to combine actual voltage readings with the analogVal reading at the Arduino, and manually check the calculations alongside my reference digital thermometer. Who on earth said that the LM35 was an 'easy to use'?
Thursday, 29 June 2017
Clock - Mk II reviewed
I've re-arranged some code, removed the second-by-second logging, and added a bit of minute-by-minute logging instead, and tweaked the adjustment delays again (968 and 48). I left the clock running for 24 hours, and this time found it had lost 2.5 seconds. The logging showed that the figures at the end of each minute were reasonably constant, but it seems that I can count on averages drifting over time, and variations of around 5ms. I'm thinking I might need to add in an hourly adjustment now, and tweak the other delays again to make sure it gains rather than loses (if it gains time - i.e. the loops are shorter than 1 second, I can add in extra compensating delays after predetermined periods - like every 10 minutes or every hour).
I've been doing a little bit of research, and I think I might be pushing the limits of the available technology anyway. From what I've read, it looks as though even the timing crystals used on the genuine Arduino boards are at best what you might call mediocre quality, with a reported accuracy of just +/- 0.5% , and the ones on Chinese clones are most probably not even that good. I've read quite a few accounts of people 'upgrading' their boards with better quality crystals, to get a more accurate millisecond timing capability (presumably after going through the same kind of exercises that I am trying).
It seems that temperature is also a factor in the potential accuracy of these crystals, though I haven't seen any figures on the degree of variance (pardon the pun) or just how different the temperatures need to be, in order to have any affect (hmm - if only I had a temperature sensor - say, like an LM35 - I could use it to plot the ambient temperature against the timing drift... Oh darn, that's right, mine's broken - LOL). However, I have read that you can get timing crystals that are enclosed in a heated thermostatically controlled enclosure (called a Crystal Oven), in order to eliminate any temperature induced variations - now that really is taking timing seriously! I won't be soldering one of those beasts onto my $5 Arduino clone!!
I've been doing a little bit of research, and I think I might be pushing the limits of the available technology anyway. From what I've read, it looks as though even the timing crystals used on the genuine Arduino boards are at best what you might call mediocre quality, with a reported accuracy of just +/- 0.5% , and the ones on Chinese clones are most probably not even that good. I've read quite a few accounts of people 'upgrading' their boards with better quality crystals, to get a more accurate millisecond timing capability (presumably after going through the same kind of exercises that I am trying).
It seems that temperature is also a factor in the potential accuracy of these crystals, though I haven't seen any figures on the degree of variance (pardon the pun) or just how different the temperatures need to be, in order to have any affect (hmm - if only I had a temperature sensor - say, like an LM35 - I could use it to plot the ambient temperature against the timing drift... Oh darn, that's right, mine's broken - LOL). However, I have read that you can get timing crystals that are enclosed in a heated thermostatically controlled enclosure (called a Crystal Oven), in order to eliminate any temperature induced variations - now that really is taking timing seriously! I won't be soldering one of those beasts onto my $5 Arduino clone!!
Monday, 26 June 2017
Clock - Mk II
The next iteration of my clock aimed at getting it to be a little more accurate. Remember - I am simply using the millis() and delay() functions to see how accurately I can keep time - for a real clock application, I would be using a Real-Time Clock module (RTC) and/or using the time library. This is simply a pedantic exercise for the sake of it.
So - in the previous version, I put together some code to set a seed time, and then to manually increment it on a periodic basis. I started that period off at 1 second - adding 1 to my seconds counter, resetting it at 60 and adding 1 to the minutes counter, and similarly resetting the minutes at 60 and incrementing the hour. Hours are reset to 0 when they reach 24.
Obviously, there is a whole bunch of code going on, doing all the incrementing and comparisons, and that takes up time which is being added to the 1 second delay, meaning each iteration through my loop is taking slightly more than 1 second, and hence my clock would lose time. I was quite shocked to see that it lost about 10 minutes in just 6 hours though - obviously there is room for improvement...
The first step in Mk II, was to add a Serial.print to the end of the loop, to show the millis() value. This revealed that each loop appeared to be taking 1031 or 1032ms, so I reduced the delay at the end of the loop to 968 to start with.
Now the loops were taking about 999 ms, meaning the clock would run fast and gain time. I increased the delay to 969, but now found the loop was running at 1001 ms! Go figure... I decided to put the delay back to 968, and then to check the millis() value each minute - perhaps I could apply a second delay once a minute to act as a compensating adjustment.
It appeared that I was gaining about 44ms per minute, so in the part of my code that resets the seconds and increments the minutes, I added another delay operation - this time for 44ms. This initially seemed to do the trick - I was now gaining just about 1ms per minute which worked out to be 1 second every 16 hours and 40 minutes. Pretty good for my needs - maybe in the next version, I could also put in an hourly adjustment to control the drift even more.
Here's the modified code, with new and amended lines highlighted yellow (actual code - not comments).
I left the sketch running overnight and checked again this morning, but... things are not going as I had hoped! After just 7 hours, the clock was about 3 seconds adrift - a lot better than the Mk I's 10 minutes, but considerably worse than the 1/2 second I was expecting. I checked back in the log on the serial monitor, and found that after running for about 8 or 9 minutes with the drift being a constant 1ms per minute, the drift suddenly started jumping to 4ms, then 6ms, then 9ms or more..! No wonder it's 3 seconds adrift already.
I am not sure exactly what to make of this. As far as I was aware - running the same set of operations in the loop repeatedly, should take exactly the same time for each loop. Obviously, if the processing has to take a different route through the logic - such as the extra processing when the seconds or minutes or hours (or all three) get reset, then the timing would be different, but if the same set of operations is run each time (as it is 59 times each minute - or the same cumulative code for an entire minute, as it is 59 times per hour), then there should be no variation in the timing.
With hindsight, I can see some very slight differences - between some loops, such as when the value is < 10, there is additional code to print an extra '0', but even that follows a distinct and predictable pattern each minute. It would not account for the variances I suddenly started getting after a few minutes, that just got bigger and bigger with no apparent pattern (other than just keeping on getting bigger).
I don't know if there are external factors that could affect this, such as voltage to the Arduino (I was running it from the USB port on my ageing laptop, and part of the time I was streaming a movie - but most of the night, it was sitting on its own in the dark, doing nothing but providing power to the Arduino). Perhaps the amount of entries in the serial monitor buffer, gradually increasing through the night is a factor (though I would have thought Arduino.exe would have been handling that independently on the PC)?
So, what next? I think I need to run a few more tests... and maybe post a question on the Arduino forum? Watch this space (or if anyone knows why the exact same code iterated a number of times can take such varying elapsed times, please let me know).
So - in the previous version, I put together some code to set a seed time, and then to manually increment it on a periodic basis. I started that period off at 1 second - adding 1 to my seconds counter, resetting it at 60 and adding 1 to the minutes counter, and similarly resetting the minutes at 60 and incrementing the hour. Hours are reset to 0 when they reach 24.
Obviously, there is a whole bunch of code going on, doing all the incrementing and comparisons, and that takes up time which is being added to the 1 second delay, meaning each iteration through my loop is taking slightly more than 1 second, and hence my clock would lose time. I was quite shocked to see that it lost about 10 minutes in just 6 hours though - obviously there is room for improvement...
The first step in Mk II, was to add a Serial.print to the end of the loop, to show the millis() value. This revealed that each loop appeared to be taking 1031 or 1032ms, so I reduced the delay at the end of the loop to 968 to start with.
Now the loops were taking about 999 ms, meaning the clock would run fast and gain time. I increased the delay to 969, but now found the loop was running at 1001 ms! Go figure... I decided to put the delay back to 968, and then to check the millis() value each minute - perhaps I could apply a second delay once a minute to act as a compensating adjustment.
It appeared that I was gaining about 44ms per minute, so in the part of my code that resets the seconds and increments the minutes, I added another delay operation - this time for 44ms. This initially seemed to do the trick - I was now gaining just about 1ms per minute which worked out to be 1 second every 16 hours and 40 minutes. Pretty good for my needs - maybe in the next version, I could also put in an hourly adjustment to control the drift even more.
Here's the modified code, with new and amended lines highlighted yellow (actual code - not comments).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | /* * Mk. II - 25/06/2017 * Checked the value of millis() at the end of each loop from Mk. I * to fine tune the delay. */ // Uses Serial.parseInt() to seed the clock. // The required string is hh:mm:ss which is 8 chars long, but we need to allow for a 'newline' char on the end // so declare a string at least 9 chars long char seedTime[9] = ""; char buffer[21] = ""; // for sprintf output // declare variables. int hh=0, mm=0, ss=0; // include LCD library #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x3F,20,4); void setup() { // Put prompt on display lcd.begin(); lcd.setCursor(0,1); lcd.print("Start Serial Monitor"); lcd.setCursor(0,2); lcd.print("Enter seed time"); lcd.setCursor(0,3); lcd.print(" (hh:mm:ss)"); // Start Serial comms with monitor Serial.begin(9600); Serial.println("Please enter the seed time in the format hh:mm:ss"); // Method 1 - parseInt - finds int values in CSV type string. Can use ":" as separator. // wait for input to be typed while (Serial.available() == 0) {} // just loops until Serial input is available // parse the input string hh = Serial.parseInt(); mm = Serial.parseInt(); ss = Serial.parseInt(); // Only expecting three values - no need to check for newline if (Serial.read() == "\n") { // end of input } // Clear the lcd lcd.clear(); } void loop() { int x = sprintf(buffer, "The time is %02d:%02d:%02d", hh, mm, ss); Serial.println(buffer); Serial.println(millis()); lcd.setCursor(0,2); lcd.print(buffer); // Using delay(1000) resulted in loop times of 1031 to 1032. // Adjusted delay to 1000-32=968. // Loop is now slightly quicker than 1 second so 'time' gains about 45ms in 1 minute. // Added an extra delay in the minute change as a correction. delay(968); ss++; if(ss==60) { ss=0; mm++; delay(44); // compensates for total loop time being very slightly less than 1 second. } if(mm==60) { mm=0; hh++; } if(hh==24) { hh=0; } } |
I left the sketch running overnight and checked again this morning, but... things are not going as I had hoped! After just 7 hours, the clock was about 3 seconds adrift - a lot better than the Mk I's 10 minutes, but considerably worse than the 1/2 second I was expecting. I checked back in the log on the serial monitor, and found that after running for about 8 or 9 minutes with the drift being a constant 1ms per minute, the drift suddenly started jumping to 4ms, then 6ms, then 9ms or more..! No wonder it's 3 seconds adrift already.
I am not sure exactly what to make of this. As far as I was aware - running the same set of operations in the loop repeatedly, should take exactly the same time for each loop. Obviously, if the processing has to take a different route through the logic - such as the extra processing when the seconds or minutes or hours (or all three) get reset, then the timing would be different, but if the same set of operations is run each time (as it is 59 times each minute - or the same cumulative code for an entire minute, as it is 59 times per hour), then there should be no variation in the timing.
With hindsight, I can see some very slight differences - between some loops, such as when the value is < 10, there is additional code to print an extra '0', but even that follows a distinct and predictable pattern each minute. It would not account for the variances I suddenly started getting after a few minutes, that just got bigger and bigger with no apparent pattern (other than just keeping on getting bigger).
I don't know if there are external factors that could affect this, such as voltage to the Arduino (I was running it from the USB port on my ageing laptop, and part of the time I was streaming a movie - but most of the night, it was sitting on its own in the dark, doing nothing but providing power to the Arduino). Perhaps the amount of entries in the serial monitor buffer, gradually increasing through the night is a factor (though I would have thought Arduino.exe would have been handling that independently on the PC)?
So, what next? I think I need to run a few more tests... and maybe post a question on the Arduino forum? Watch this space (or if anyone knows why the exact same code iterated a number of times can take such varying elapsed times, please let me know).
Subscribe to:
Comments (Atom)
