Now that we've covered the function and design of the logger device, let's look at a few of the obstacles.
Unexpected Data:
One of the functions that needed to be coded and tested early on was dumping the light data to a PC. I used a C# program that I wrote for doing two way serial communication and added features to have to send and show data in either ASCII or hex.
So the issue I ran into was that data seemed to be getting distorted, specifically for sunny conditions. I wasn't seeing any values greater than 0x7F, which is the maximum ASCII value (7 bits). However this wasn't immediately noticeable as most of the values I was receiving were 0x3F. It almost looked like maybe there was a memory issue and that was a default value of some sort. My other thought was that maybe there was a baud rate issue and I kept losing that first bit somehow. I was pulling at straws. I spent a whole bunch of time looking at scope captures of the data and measuring pulses manually to compute the baud error to no avail. Then I took note of how the ASCII value of 0x3F is a '?'. Maybe there was something to that.
So I started poking around in my C# code for a reason that portions of my data was being converted to '?'s. I was using hte built-in SerialPort object that is part of .NET and upon received data used the "ReadChar()" method because it returned printable characters. I had added the ability to print hex as an afterthought, and as such, simply formatted the returned value as a hex byte when printing to the window. Seeing as the "ReadChar" method actually returns an integer value, I assumed I was getting the raw data.
Turns out I was wrong. The SerialPort object allows for the setting of a text encoder, which I believe by default is ASCII. And ASCII does not support values over 0x7F. A little code rewrite using the "ReadByte()" and all was good. My firmware or circuit were fine from the start. Admittedly, the PC side of things is usually much easier to develop and debug, which gave me a false sense of security. I assumed my debug tool worked because it didn't fail catastrophically (as embedded software often can). But it usually helps to know what goes on under the hood, otherwise some issues are seemingly impossible.
Small Optomizations:
Seeing as the logger was going to run off of batteries, I took some care to reduce power draw. I only had so many I/O pins which meant I had to be mindful of idle states when combining functions. So for instance, I used a PNP for both the TX and the power to the ambient light sensor and buffer amp in order that they both share the same off state. I only turn the sensor and amp on for a very short period of time, which does turn on the TX transistor (Q4), but the TX resistor is sized to reduce current draw. It's a compromise, but at least they are both off for the vast majority of the time. The op amp was even chosen amongst the ones I had (and ones I would have preferred to use up) because of its lower supply current. Fortunately the memory chip only draws a 1uA while idle, leaving it power on all the time is inconsequential. And the RX transistor is stuck off unless something unless a com port is attached.
But hardware isn't the only place to save on power. Efficient code and good use of microcontroller features helps a lot. The most obvious features is the SLEEP function. In a 24 hour logging period, the device is inactive 99.9945% of the time. By putting the MCU in a lower power state, the circuit hardly draws any power (my secondary multimeter of suspect accuracy claims around 60uA, which actually seems a little high). This amounts to about 1.5mA hours spent idling over 24 hours. Not too bad.
But some code efficiency can also help. Ideally, you don't want to be waiting for anything if it can be helped. In my case, it took a certain amount of time for the sensor output and internal voltage reference to settle when the MCU woke up and turned everything on.
Improvements:
There are of course other improvements to be made on this device though I'm not unhappy with its current state. Larger resistors can be used for both the I2C pull-ups and for the TX and RX bits of the circuit as the data rates for both are rather slow. Mechanically I can shade the light sensor so that the sense resistor can be made larger reducing its current draw. It'd also be nice to slap in a bluetooth module making connection to a computer easier. Maybe some day....
So the issue I ran into was that data seemed to be getting distorted, specifically for sunny conditions. I wasn't seeing any values greater than 0x7F, which is the maximum ASCII value (7 bits). However this wasn't immediately noticeable as most of the values I was receiving were 0x3F. It almost looked like maybe there was a memory issue and that was a default value of some sort. My other thought was that maybe there was a baud rate issue and I kept losing that first bit somehow. I was pulling at straws. I spent a whole bunch of time looking at scope captures of the data and measuring pulses manually to compute the baud error to no avail. Then I took note of how the ASCII value of 0x3F is a '?'. Maybe there was something to that.
So I started poking around in my C# code for a reason that portions of my data was being converted to '?'s. I was using hte built-in SerialPort object that is part of .NET and upon received data used the "ReadChar()" method because it returned printable characters. I had added the ability to print hex as an afterthought, and as such, simply formatted the returned value as a hex byte when printing to the window. Seeing as the "ReadChar" method actually returns an integer value, I assumed I was getting the raw data.
Turns out I was wrong. The SerialPort object allows for the setting of a text encoder, which I believe by default is ASCII. And ASCII does not support values over 0x7F. A little code rewrite using the "ReadByte()" and all was good. My firmware or circuit were fine from the start. Admittedly, the PC side of things is usually much easier to develop and debug, which gave me a false sense of security. I assumed my debug tool worked because it didn't fail catastrophically (as embedded software often can). But it usually helps to know what goes on under the hood, otherwise some issues are seemingly impossible.
Small Optomizations:
Seeing as the logger was going to run off of batteries, I took some care to reduce power draw. I only had so many I/O pins which meant I had to be mindful of idle states when combining functions. So for instance, I used a PNP for both the TX and the power to the ambient light sensor and buffer amp in order that they both share the same off state. I only turn the sensor and amp on for a very short period of time, which does turn on the TX transistor (Q4), but the TX resistor is sized to reduce current draw. It's a compromise, but at least they are both off for the vast majority of the time. The op amp was even chosen amongst the ones I had (and ones I would have preferred to use up) because of its lower supply current. Fortunately the memory chip only draws a 1uA while idle, leaving it power on all the time is inconsequential. And the RX transistor is stuck off unless something unless a com port is attached.
But hardware isn't the only place to save on power. Efficient code and good use of microcontroller features helps a lot. The most obvious features is the SLEEP function. In a 24 hour logging period, the device is inactive 99.9945% of the time. By putting the MCU in a lower power state, the circuit hardly draws any power (my secondary multimeter of suspect accuracy claims around 60uA, which actually seems a little high). This amounts to about 1.5mA hours spent idling over 24 hours. Not too bad.
But some code efficiency can also help. Ideally, you don't want to be waiting for anything if it can be helped. In my case, it took a certain amount of time for the sensor output and internal voltage reference to settle when the MCU woke up and turned everything on.
Improvements:
There are of course other improvements to be made on this device though I'm not unhappy with its current state. Larger resistors can be used for both the I2C pull-ups and for the TX and RX bits of the circuit as the data rates for both are rather slow. Mechanically I can shade the light sensor so that the sense resistor can be made larger reducing its current draw. It'd also be nice to slap in a bluetooth module making connection to a computer easier. Maybe some day....








