The new code seems to be working. I've ordered some more parts from online so that I can actually build these sensors into some real world rigs.
The new code is here, on the Adafruit site.
I'm going to try to keep the top post updated with the new code so people don't have to search through the comments (there aren't too many of them. This went pretty quickly). I'm going to try to make the code a little more functional, and include some of the other configuration options offered by the ADXL345.
Right now, the only thing that is really tested and seems to work well is the readAccel() function. Calling this function will spit out the three accelerometer values (a raw number, not corrected with a gravity coefficient). With my rig I've been able to get over 100 values per second (I think... I can't find my scratch pad).
It spits out all three of the values because of the way the ADXL is designed to release data. If you don't pull all three values, and instead just pull one, the ADXL "over-writes" the other two values in the stack with new data. I figured it would be easier to just let the coder handle a couple of data values that they don't need, rather than give them an option that might give funky results later if they didn't dive deep into the datasheet.
I need to write my program for handling and graphing the data obtained by the ADXL345 for my project. I'm probably going to have a buffer (of a user determined size) of values from the ADXL. When the system detects an event it saves the buffer and continues writing readings until A) a specified amount of time or B) some sort of quiescent period is detected or C) an external "stop" signal is received. I then want to output the data on a series of graphs showing the acceleration and combined vectors over time. Again, this will probably be written in Python. The mature version will hopefully use some sort of real-time display while recording the data.
Medic for Life
As I'm moving closer and closer to medical school, I seem to be doing less and less medicine. From helping build a local bar as a volunteer (a worthy cause, in my book), to hack-building cool gadgets. I'm picking up bizarre skill sets left and right. This is adding to the already diverse skill sets I had acquired on my previous jobs. I'll detail my rants, raves and experiences here.
Sunday, April 28, 2013
Preliminary Library for the ADXL345 in Python
Labels:
Accelerometer,
Adafruit,
ADXL345,
DIY,
Hacks,
I2C,
Linux,
Python,
Raspberry Pi
| Reactions: |
Saturday, April 20, 2013
The ADXL345, Python and Raspberry Pi
I'm working on logging data from the ADXL345 accelerometer for a DIY physics project for a friend of mine (OK, it's for me too because it involves fun physics). I wasn't able to find a library for running the ADXL345 using Python, so I spent the day building one.
The code is over on Adafruit's forums, and it is very much a work in progress. I'm reading data from the board and it looks like I'm able to set configuration options pretty easily. Right now this is very much a hack in progress. There are parts lying all over the floor, it isn't portable and it isn't easily used.
The problem is that the ADXL reports acceleration using two eight-bit values. Here's the quick start sheet, here.
The first register uses all 8-bits to report data. The second register uses four of the bits to report data, the other four are used to report the "sign" of the data (positive or negative).
I can't, for the life of me, figure out how to make this data usable, elegantly.
The code is over on Adafruit's forums, and it is very much a work in progress. I'm reading data from the board and it looks like I'm able to set configuration options pretty easily. Right now this is very much a hack in progress. There are parts lying all over the floor, it isn't portable and it isn't easily used.
The problem is that the ADXL reports acceleration using two eight-bit values. Here's the quick start sheet, here.
The first register uses all 8-bits to report data. The second register uses four of the bits to report data, the other four are used to report the "sign" of the data (positive or negative).
I can't, for the life of me, figure out how to make this data usable, elegantly.
Labels:
Accelerometer,
Adafruit,
ADXL345,
I2C,
project,
Python,
Raspberry Pi
| Reactions: |
Sunday, March 31, 2013
If it ain't broke...
I've spent weeks trying to figure out how I broke my Raspberry Pi. Actually... How I broke two of them.
Well, I didn't actually break them. Just the sensors attached to them.
Well, I didn't actually break them, it's just that they weren't reading correctly.
Here's the story:
I've been working on a couple of I2C sensors to tie into my Raspberry Pi. The idea is to read the sensors at specific intervals, log the data, and then serve up some nice graphs. I've been using the BMP085 temperature and pressure sensor, the TSL2561 light sensor, and the TMP102 temperature sensor (All those links go to the Adafruit forums specific to those sensors and the Raspberry Pi).
A group of us were collaborating on the TSL2561 (Hi, csalty!), when I upgraded to the newer version of Adafruit_I2C and the Adafruit_BMP085. That's where everything went sideways.
I spent days looking at the datasheet and the Adafruit_BMP085 code. Some of the stuff just doesn't make sense to me. It doesn't make sense to the point that I wrote the devs saying "This is broken".
It's not, and that's pretty embarrassing. It really looks like something in the Adafruit_I2C code changed how it pulls the information from the BMP085. If you're looking for solutions, enable the debug mode, and check your calibration information. Mine was VERY off using that version of Adafruit_I2C (Impossible temperatures and unstable in nature reading 200 degrees one minute negative 70 the next). Once I switched some of the functions to the older version, things went well. The kludge-version of Adafruit_I2C that I'm using is listed here: Modified Adafruit_I2C.py.
I also made a very specific change to the Adafruit_BMP085.py code. I allowed the code to pass a specified bus number down the "stack" to the I2C code. By default it does not specify a bus, and will allow the new I2C software to determine which version of the Raspberry Pi is being used, selecting the default GPIO header bus. This way, all you have to do is call the BMP085. It will fill in the default address, the default mode, and the default bus. If you (like me) are using both I2C buses on your Raspberry Pi, then you MUST specify when you are using the "non-standard" bus. The way the Adafruit_I2C.py code is written, it will only look for the version of the board and assign the "default" bus. It has no way of knowing which bus you want to use.
I also set up the BMP085 code to pass the debug state down the code stack. I figure if you're interested in debugging the BMP085, you're also going to be interested in debugging what is happening with the I2C code. As part of the BMP085 calibration data, I also set it up to print out which I2C bus is being specified.
I need to make these changes to the TSL2561 code and the TMP102 code. Both of these sensors appeared to be working just fine with the new Adafruit_I2C.py code (I've checked to make sure).
I've changed my project a little bit. Now I'm running two parallel sets of sensors on the two different buses. Each bus has a TSL2561 and a BMP085 sensor. I'm logging the temperature, light level, and pressure every sixty seconds or so. I'm manually able to generate all kinds of charts, but for right now I'm going to keep it manual. I'll let the system run while I'm at work this week (four days), and if everything looks OK, I'll work on re-writing the webpage code.
Well, I didn't actually break them. Just the sensors attached to them.
Well, I didn't actually break them, it's just that they weren't reading correctly.
Here's the story:
I've been working on a couple of I2C sensors to tie into my Raspberry Pi. The idea is to read the sensors at specific intervals, log the data, and then serve up some nice graphs. I've been using the BMP085 temperature and pressure sensor, the TSL2561 light sensor, and the TMP102 temperature sensor (All those links go to the Adafruit forums specific to those sensors and the Raspberry Pi).
A group of us were collaborating on the TSL2561 (Hi, csalty!), when I upgraded to the newer version of Adafruit_I2C and the Adafruit_BMP085. That's where everything went sideways.
I spent days looking at the datasheet and the Adafruit_BMP085 code. Some of the stuff just doesn't make sense to me. It doesn't make sense to the point that I wrote the devs saying "This is broken".
It's not, and that's pretty embarrassing. It really looks like something in the Adafruit_I2C code changed how it pulls the information from the BMP085. If you're looking for solutions, enable the debug mode, and check your calibration information. Mine was VERY off using that version of Adafruit_I2C (Impossible temperatures and unstable in nature reading 200 degrees one minute negative 70 the next). Once I switched some of the functions to the older version, things went well. The kludge-version of Adafruit_I2C that I'm using is listed here: Modified Adafruit_I2C.py.
I also made a very specific change to the Adafruit_BMP085.py code. I allowed the code to pass a specified bus number down the "stack" to the I2C code. By default it does not specify a bus, and will allow the new I2C software to determine which version of the Raspberry Pi is being used, selecting the default GPIO header bus. This way, all you have to do is call the BMP085. It will fill in the default address, the default mode, and the default bus. If you (like me) are using both I2C buses on your Raspberry Pi, then you MUST specify when you are using the "non-standard" bus. The way the Adafruit_I2C.py code is written, it will only look for the version of the board and assign the "default" bus. It has no way of knowing which bus you want to use.
I also set up the BMP085 code to pass the debug state down the code stack. I figure if you're interested in debugging the BMP085, you're also going to be interested in debugging what is happening with the I2C code. As part of the BMP085 calibration data, I also set it up to print out which I2C bus is being specified.
I need to make these changes to the TSL2561 code and the TMP102 code. Both of these sensors appeared to be working just fine with the new Adafruit_I2C.py code (I've checked to make sure).
I've changed my project a little bit. Now I'm running two parallel sets of sensors on the two different buses. Each bus has a TSL2561 and a BMP085 sensor. I'm logging the temperature, light level, and pressure every sixty seconds or so. I'm manually able to generate all kinds of charts, but for right now I'm going to keep it manual. I'll let the system run while I'm at work this week (four days), and if everything looks OK, I'll work on re-writing the webpage code.
| Reactions: |
Sunday, February 24, 2013
Two I2C buses on the Raspberry Pi
I'm hoping this post can clear up some mis-information regarding the two I2C buses on the Raspberry Pi Model B rev 2.
In the upper left hand corner of the board you can see the GPIO header. Below that is the P5 header footprint, a 2x4 series of vias. You won't see the P5 label until you flip the board over.
Now, there are some folks that will tell you the only way to get to the second I2C bus is to access the camera S5 header (or the S2 header). That would involve some incredible soldering work, or a socket. I don't have the socket, and my hands aren't good enough to solder at that pitch.
However, I can solder that P5 header. The unfortunate thing is that the P5 header is really close to the GPIO header. Using the P5 header while using Lady Ada's Pi Cobbler header may be problematic. I took some long headers and soldered them in place, at a slight angle.
I used a 2x5 socket on the header, and spaced it with a penny (between the 2x5 socket and the ribbon cable).
The process is actually pretty easy. If you're a novice solderer you shouldn't be too daunted by this task. Hey, the Pi itself is $35. It's OK.
Once you get that done, you need to run some code. I'll post the Python 3.x code in a bit. Here's a link to the original code. All that needs to be done for the Python 3.x code is to change the print statements to print() functions. Here's the link to the RaspberryPi.org forums, where bgreat posted the code:
http://www.raspberrypi.org/phpBB3/viewtopic.php?f=44&t=33092
In hindsight, I should have looked at putting a 2x4 socket there. I'm just not sure that I have any.
Now, there are some folks that will tell you the only way to get to the second I2C bus is to access the camera S5 header (or the S2 header). That would involve some incredible soldering work, or a socket. I don't have the socket, and my hands aren't good enough to solder at that pitch.
However, I can solder that P5 header. The unfortunate thing is that the P5 header is really close to the GPIO header. Using the P5 header while using Lady Ada's Pi Cobbler header may be problematic. I took some long headers and soldered them in place, at a slight angle.
I used a 2x5 socket on the header, and spaced it with a penny (between the 2x5 socket and the ribbon cable).
The process is actually pretty easy. If you're a novice solderer you shouldn't be too daunted by this task. Hey, the Pi itself is $35. It's OK.
Once you get that done, you need to run some code. I'll post the Python 3.x code in a bit. Here's a link to the original code. All that needs to be done for the Python 3.x code is to change the print statements to print() functions. Here's the link to the RaspberryPi.org forums, where bgreat posted the code:
http://www.raspberrypi.org/phpBB3/viewtopic.php?f=44&t=33092
In hindsight, I should have looked at putting a 2x4 socket there. I'm just not sure that I have any.
Labels:
Adafruit,
I2C,
logger,
Raspberry Pi,
sensors
| Reactions: |
Friday, January 11, 2013
Parallelism in Hacking
I spent yesterday morning working on the datalogger, specifically making it WiFi capable. This morning, I slept in, made my coffee and checked the news. Over on Hackaday, Jose has created an Arduino/Pi/WiFi/X-Bee environmental monitor. He's got his own webspace, uc4fun, where he's hosting the notes on his project. A lot more professional looking than mine.
He's essentially doing my project (If he knows I exist, he's shaking his head saying "That guy's doing MY project"). However, he's doing it in a completely different fashion, which is awesome. I think he's using a mix of I2C sensors (he's using the TMP102 and the BMP085) and a Sparkfun humidity sensor (Dude! New Product Friday.... 'cuse me while I go browse...).
I think he went with the doubled up microprocessor approach because it allows him to use the ADC's on the Arduino. So far, I've been severely limited in the sensors I can use on my build because I'm only using I2C and binary digital sensors. His complexity gets him some serious advantages, but is also one of the main things I want to avoid (He's probably writing code for both the Arduino and the Pi. That'll give me headaches). I sent him a message on the Hackaday board asking why he made the choices he did. Looking at his build and presentation, he's going to have some good answers.
I definitely wanted to avoid the multiple radio links. Given my history with RF links, I'd like to keep that as simple as possible.
He's essentially doing my project (If he knows I exist, he's shaking his head saying "That guy's doing MY project"). However, he's doing it in a completely different fashion, which is awesome. I think he's using a mix of I2C sensors (he's using the TMP102 and the BMP085) and a Sparkfun humidity sensor (Dude! New Product Friday.... 'cuse me while I go browse...).
I think he went with the doubled up microprocessor approach because it allows him to use the ADC's on the Arduino. So far, I've been severely limited in the sensors I can use on my build because I'm only using I2C and binary digital sensors. His complexity gets him some serious advantages, but is also one of the main things I want to avoid (He's probably writing code for both the Arduino and the Pi. That'll give me headaches). I sent him a message on the Hackaday board asking why he made the choices he did. Looking at his build and presentation, he's going to have some good answers.
I definitely wanted to avoid the multiple radio links. Given my history with RF links, I'd like to keep that as simple as possible.
Labels:
BMP085,
Builds,
Computers,
DIY,
Equipment,
Hackaday,
Hacks,
I2C,
logger,
logging,
node,
project,
Python,
Raspberry Pi,
sensors,
Sparkfun,
tech,
techniques,
Technology,
TMP102
| Reactions: |
Thursday, January 10, 2013
Raspberry Pi Remote Data Logger: Now with tons more remote!
I spent the morning re-building, re-making, re-everything-ing my original version 1 Raspberry Pi model B (smaller amount of memory, two USB ports and an ethernet port). I was going to clone my work, essentially copy the SD card, but I decided that this would just carry over all of the crap from my original forays into Linux.
Interesting side note, the Adafruit boards won't let me use the word "crap" in my posts on there. I thought that was pretty hysterical, given my sailor mouth (Today's post is here).
I put the Adafruit Linux Distro, Occidentalis onto a spare 8GB memory card. Then I started working through the essentials to get the board ready for SSH and VNC over a WiFi connection. Finally, I kept working through the required Python modules for my code to work (I did pull the code over from my working Pi using a USB stick). In short order, I got everything up and running. Remotely. I documented the steps on the Adafruit blog, here.
I really feel like I should get a reward for the documentation.
The system is now in my kitchen, with a sensor cluster out the window. I'm logging internal temperature and pressure, and external temperature. I took the motion sensor off. I need to work on a new modality for that.
I've been logging motion on a binary basis (does the sensor see motion or not, each minute). I'm only polling the sensor every minute. You could sneak by the sensor by walking past it within the polling window. I know the sensor registers motion and then continues to read motion for a short period of time (I think it's about 5 seconds, from playing with it before).
Instead, what I want to do, is have the sensor poll every couple of seconds, and count the number of motion hits per minute. Then, when it graphs the motion, it graphs not just whether motion was seen or not, but how much motion.
I need to figure out how to implement that in terms of Python code. I'll need to have the motion sensor polling every couple of seconds, remembering the count until it is reset, and returning that count to the requesting code.
First, I need to examine the sensing characteristics of the motion sensor. I think I'm going to break out the Arduino for that.
I think a similar modality could be used for the gyro/accelerometer that I have on the board. I still don't have the slightest clue as to how to read the values for that thing. I'm not really interested in the actual values, but I'm really interested in major variances and the magnitude of those variances.
The next sensor idea is using a MaxBotix ultrasound sensor to look at motion in my hallway. I'm also thinking that one could be dedicated to detecting the position of the front door (and back door, for that matter). I'm trying to decide if I should use an ultrasonic sensor for both. I've got a cheapie IR proximity sensor that could be used for the front door. MaxBotix makes a series of I2C ultrasound sensors which would be an easy integration. It looks like the address on the MaxBotix sensors can be reassigned, so I could use multiple sensors on the same I2C bus.
I'm in a rental place right now. That means I can't go tearing the place up to run wires and implement these ideas. On the flip side, my landlords are very cool. I think they'd support some of what I'm doing. All that being said, I think I need to consider more nodes and less wiring.
If I can figure out how to do this wirelessly, it'll be easy as pie to get everything working on a wired network (I'm probably going to regret saying that later).
Interesting side note, the Adafruit boards won't let me use the word "crap" in my posts on there. I thought that was pretty hysterical, given my sailor mouth (Today's post is here).
I put the Adafruit Linux Distro, Occidentalis onto a spare 8GB memory card. Then I started working through the essentials to get the board ready for SSH and VNC over a WiFi connection. Finally, I kept working through the required Python modules for my code to work (I did pull the code over from my working Pi using a USB stick). In short order, I got everything up and running. Remotely. I documented the steps on the Adafruit blog, here.
I really feel like I should get a reward for the documentation.
The system is now in my kitchen, with a sensor cluster out the window. I'm logging internal temperature and pressure, and external temperature. I took the motion sensor off. I need to work on a new modality for that.
I've been logging motion on a binary basis (does the sensor see motion or not, each minute). I'm only polling the sensor every minute. You could sneak by the sensor by walking past it within the polling window. I know the sensor registers motion and then continues to read motion for a short period of time (I think it's about 5 seconds, from playing with it before).
Instead, what I want to do, is have the sensor poll every couple of seconds, and count the number of motion hits per minute. Then, when it graphs the motion, it graphs not just whether motion was seen or not, but how much motion.
I need to figure out how to implement that in terms of Python code. I'll need to have the motion sensor polling every couple of seconds, remembering the count until it is reset, and returning that count to the requesting code.
First, I need to examine the sensing characteristics of the motion sensor. I think I'm going to break out the Arduino for that.
I think a similar modality could be used for the gyro/accelerometer that I have on the board. I still don't have the slightest clue as to how to read the values for that thing. I'm not really interested in the actual values, but I'm really interested in major variances and the magnitude of those variances.
The next sensor idea is using a MaxBotix ultrasound sensor to look at motion in my hallway. I'm also thinking that one could be dedicated to detecting the position of the front door (and back door, for that matter). I'm trying to decide if I should use an ultrasonic sensor for both. I've got a cheapie IR proximity sensor that could be used for the front door. MaxBotix makes a series of I2C ultrasound sensors which would be an easy integration. It looks like the address on the MaxBotix sensors can be reassigned, so I could use multiple sensors on the same I2C bus.
I'm in a rental place right now. That means I can't go tearing the place up to run wires and implement these ideas. On the flip side, my landlords are very cool. I think they'd support some of what I'm doing. All that being said, I think I need to consider more nodes and less wiring.
If I can figure out how to do this wirelessly, it'll be easy as pie to get everything working on a wired network (I'm probably going to regret saying that later).
Sunday, December 16, 2012
Integrating the TMP102 sensor with the datalogger, and I2C bus lengths
The TMP102 is an I2C sensor available on a breakout board from Sparkfun TMP102. It's pretty cheap, under $10. It will actually allow you to have multiple sensors on the same I2C bus just by jumpering an address pin.
I'm working on creating a software module to decode the output from the sensor. So far it isn't straight forward, at least for an amateur. If I understand correctly, the sensor reports the readings in a backwards fashion. I'm not sure I've decoded the output correctly, but I'm close. Once I get that ironed out, I'll post the code up.
I started playing with I2C bus lengths. I heard that the practical length was less than a meter. I've got around a 2-3 meter CAT-5 cable set up running the TMP102. It's dangling outside the window, inside a tupperware container, and appears to be working just fine. I'm using Sparkfun RJ-45 Jacks and breakout boards. It adds a couple of bucks to the cost of the project, but it makes for great modularity. It's also going to let me do some cable run tests. Eventually I'll post those up as well.
I modified the jacks and breakout boards slightly. In place of a simple header, I used Arduino 8-pin stackable headers. That way, I can easily add a second sensor (or more) at the cable end, while still being able to easily breadboard it. So far it's working great.
The goal with this setup is to have two sets of environmental sensors. One on the Raspberry Pi itself, and the other just slightly remote from the Raspberry Pi. This sensor set could be outside a window, inside a terrarium/fish tank, inside a science project (fermenter? soil analyzer? hot water heater?), all kinds of possibilities.
If I can make the software scale-able, anyone could add all kinds of sensors to the system and have it easily recordable. The only drawback would be writing new sensor drivers for each set of sensors. That's where I'm having a fair amount of difficulty now.
It looks like I was wrong when I figured out the size of the data files. Right now, the datafiles appear to be much smaller, despite my cramming more information into them (Temp1, Temp2, Pressure, Motion Sensor, Time, Log Level). I think I want to change the logging system even further so that it creates a better record of values. Right now I'm saving a string for each sensor cycle with just the sensor values. The software is written so that it assumes a certain value is in a certain order in the string. That's great, as long as no one else is adding sensors to the system, and you only look a certain way.
I'm wondering if I can create a log with each sensor cycle recording a dictionary. Then I could easily write code to examine which sensors were polled for each sensor cycle. I could easily pull all the sensor values, or some of the sensor values. I could have some sensors polled more often than others.
I need to grab a second Raspberry Pi, and start thinking about how to pull all the sensors nodes together, into one easy to read display.
I'm working on creating a software module to decode the output from the sensor. So far it isn't straight forward, at least for an amateur. If I understand correctly, the sensor reports the readings in a backwards fashion. I'm not sure I've decoded the output correctly, but I'm close. Once I get that ironed out, I'll post the code up.
I started playing with I2C bus lengths. I heard that the practical length was less than a meter. I've got around a 2-3 meter CAT-5 cable set up running the TMP102. It's dangling outside the window, inside a tupperware container, and appears to be working just fine. I'm using Sparkfun RJ-45 Jacks and breakout boards. It adds a couple of bucks to the cost of the project, but it makes for great modularity. It's also going to let me do some cable run tests. Eventually I'll post those up as well.
I modified the jacks and breakout boards slightly. In place of a simple header, I used Arduino 8-pin stackable headers. That way, I can easily add a second sensor (or more) at the cable end, while still being able to easily breadboard it. So far it's working great.
The goal with this setup is to have two sets of environmental sensors. One on the Raspberry Pi itself, and the other just slightly remote from the Raspberry Pi. This sensor set could be outside a window, inside a terrarium/fish tank, inside a science project (fermenter? soil analyzer? hot water heater?), all kinds of possibilities.
If I can make the software scale-able, anyone could add all kinds of sensors to the system and have it easily recordable. The only drawback would be writing new sensor drivers for each set of sensors. That's where I'm having a fair amount of difficulty now.
It looks like I was wrong when I figured out the size of the data files. Right now, the datafiles appear to be much smaller, despite my cramming more information into them (Temp1, Temp2, Pressure, Motion Sensor, Time, Log Level). I think I want to change the logging system even further so that it creates a better record of values. Right now I'm saving a string for each sensor cycle with just the sensor values. The software is written so that it assumes a certain value is in a certain order in the string. That's great, as long as no one else is adding sensors to the system, and you only look a certain way.
I'm wondering if I can create a log with each sensor cycle recording a dictionary. Then I could easily write code to examine which sensors were polled for each sensor cycle. I could easily pull all the sensor values, or some of the sensor values. I could have some sensors polled more often than others.
I need to grab a second Raspberry Pi, and start thinking about how to pull all the sensors nodes together, into one easy to read display.
Subscribe to:
Posts (Atom)


