Spirit levels are ubiquitous in various fields of design and they serve an essential purpose of indicating the levelness of the surface in question. Traditional techniques comprise of an air bubble trapped in a liquid which balances itself in the center when held level; however, it requires a good visual check to determine the readings.
If you try to reason out what determines the levelness of a surface, you will soon come to realize that it is the 2D orientation that determines the level, i.e. height is irrelevant, since a crooked surface will still remain crooked even if you raise it up by 1 or 100m. (Assuming of course you raise the entire surface equally). So in order to build a digital prototype we need to sense the orientation of the surface in question, lucky for us we already have a sensor available: the humble accelerometer.
Here, we can sense the gravity vector and determine the orientation of the sensor and hence any object that is rigidly held with the sensor. Not only this, but by storing the sensor values, you can also compare the inclination of various surfaces, thus now every model you build which contains parallel surfaces will all be perfectly inclined with respect to each other but only if you build the digital spirit level.
Fig. 1: Prototype of ATMega168 based Digital Spirit Level Indicator
Figure 9 – Powered Down Assembly
ATmega168 Development Stick
The entire project is built around the ATmega168 Development Stick which is a compact and handy unit. The stick is enabled with USB port for communication with latest laptops. The stick consists of the 32pin TQFP version of the ATmega168 along with power regulation and crystal oscillators as well as pin outs for the LCD module which is pretty neat since we don’t have to hookup wires to all those pins. Besides that, all the I/O pins have been brought out for expansion and we will be using some of them to interface our peripherals.
Fig. 2: Typical Image of ATMega168 Development Stick
We will need 2 ADC inputs for each axis while the development stick has a total of 8 ADC channels, so feel free to select the ones you wish, we shall be using channel 0 and channel 1, i.e. pins PC0, PC1. To trigger the calibration, we will need to hook up a pushbutton switch to a pin, and so we need an input which is pin PC2 for our code, also it is always nice to have an indicator to give you some visual feedback that the code you burnt is running and so we need an output to which we can connect an LED, so for us it is pin PD7. Lastly, we just need to mount an LCD to the header pins already populated on the stick, that’s how easy it is since the potentiometer needed to vary the display contrast is already on the board.
Accelerometer
Now comes the critical sensing part. For the accelerometer we used an analog chip from Freescale semiconductors. The chip itself was very tiny and hence a module has been used. Most accelerometers today are produced in tiny non-hobbyist friendly packages so please keep note of the same while selecting your module. Most also require additional capacitors for filtering, so when you buy a module make you sure you get what you pay for.
The one we will be using today is the MMA6361L 2-axis accelerometer which provides an analog output for each axis. You do get accelerometers with digital interfaces, but they are a bit cumbersome to use, especially if you are just starting out, so for today we shall stick with the one mentioned above. Note that any other analog accelerometer will work just as well, you may however, have to change the way the computations are performed.
Fig. 3: Pin Diagram of MMA6361L IC
The pin configuration for the accelerometer is shown above. Most of them will not be used in normal operation mode, which further simplifies our design. Pin 2 provides the X-axis output in analog voltage ranging from about 0.5V to about 3.2V, pin 3 provides the &-axis value within the same range. Pin 6 is the supply pin (3.3V) while pin 5 and pin13 should be connected to ground.
The module has a low power sleep mode mainly used to reduce power consumption; this is activated by pin 7. The sleep signal is active low, meaning logic 0 (GND) will activate sleep mode, so we need to tie this pin to logic 1 (3.3V) to enable the sensor. Lastly the sensor has dual range capability, i.e. can sense +/- 1.5g as well as +/-6g, this is what the g-select pin is responsible for. Applying logic 0 to this pin activates the +/- 1.5g range with a sensitivity of 206mv/g, while applying logic 1 activates the +/-6g with a sensitivity of 800mv/g.
[_Note: g = acceleration due to gravity = 9.81m/s2_]
Since all we are interested in is measuring static acceleration i.e. the response on account of the earth’s gravity vector; we will be concerned with only +/- 1g, hence using the +/-1.5g setting will provide us with a more granular output and hence better response. So we tie pin 10 to logic 0.
As the sensor responds to tilt along the 2-axis and hence the output varies in proportion to the same. The sensor provides a stable neutral value when held level, and this value is about 1.65V on each axis. Tilting the sensor along each axis will produce an output greater or less than this neutral value, all we need to do is sense this variation and translate the same into tilt values. Before we move on to actual computation, let’s spend some time on the reference model to be used.
To keep it simple, a reference model will help us determine the actual orientation of the surface just by knowing some information. Since we have a 2-axis accelerometer, we will obtain 2 values; consequently our model will need to somehow use these values to specify the orientation. The simplest terminology used is roll/pitch.
Fig. 4: Image showing Roll Pitch Illustration
The same has been illustrated above. Picture a table in front of you, and assume the top surface is as shown above, now if you rotate it towards your right hand side; you actually roll the table in the positive sense, if you roll it towards the left you roll it in the negative sense. Similarly if you lift the furthermost end (directly away from you) of the table above the one closest to you, you are said to be pitching the table in the positive direction, while doing the opposite will be pitching it in the negative direction.
Now that we have that entire thing in place, let us look at the accelerometer output.
Fig. 5: Image showing sample response of Accelerometer
The orientation of the module with respect to the reference frame is shown above, along with some sample output voltages when the module is tilted into the corresponding axis. So keeping our convention in mind, when the module is rolled right, the X-axis output voltage increases above the neutral value of 1.65V, when it is rolled left, the voltage drops below that of the neutral value.
Similarly for the pitch, when the module is pitch down (lowered into the +Y axis), the Y-axis output voltage increases above the neutral value of 1.65V and the opposite takes place when the module it pitched up.
So that’s the underlying principle involved in the sensing orientation.
ADC Output
The ADC unit on the MCU works by taking the ADC reference voltage and breaking down into smaller chunks based on the ADC resolution. The ADC resolution is nothing but the number of bits used to represent the output. The ATmega168 has a 10-bit ADC, meaning the output can range from 0-1023. So the MCU breaks down the reference voltage to 1024 chunks. The development board has the ADC reference voltage tied to 5V, ideally for this sensor the voltage should be 3.3V since that is the maximum voltage the sensor is capable of signaling, but 5V will just work fine for our application. So taking 5V as reference the ADC breaks it down into 1024 chunks of about 5V/1024 = 4.8mV each. So if the ADC gives you a value of 10, it means the voltage at the ADC pin is 10*4.8mV, about 48mV, similarly for a full scale output of 1024, the voltage at the ADC pin is 1024*4.8mV which is about 4910mV (the error is due to rounding of the bit value).
For our application we do not need to know the raw values, all we need to do is obtain the ADC counts for 5 different position and we can compute the remaining from there since there exists a linear relationship between the output voltage and the degree of tilt. Sample values for the module used are listed below.
Position
|
X ADC count
|
Y ADC count
|
Neutral
|
320
|
320
|
Roll 90degrees
|
480
|
320
|
Roll -90degrees
|
160
|
320
|
Pitch 90 degrees
|
320
|
160
|
Pitch -90degrees
|
320
|
480
|
Figure 4 – ADC Response
It can be observed that the ADC count increases/decreases by about 160 units for +90/-90 variation (-90/+90 for pitch), so we can estimate the gradient to be 90/160 degrees/count.
Using the data above it is easy to compute the angle of inclination for any other orientation, simply take the ADC count value and subtract the neutral value (320) from it, this gives us the change in ADC counts for the tilt, we simply need to multiply this with the gradient (90/160) to obtain the resultant inclination along the axis. There needs to be a sign reversal for pitch, because of the choice of our reference model and the sensor axis orientation.
To formulate the same:
Angle of Inclination = (ADC_Count – 320) * 90 / 160
A count of 400 would yield an inclination of (400 – 320) * 90 / 160 = 80 * 90 / 160 = 45 degree, while a count of 240 would yield an inclination of (240 – 320) * 90 / 160 = (-80) * 90 / 160 = -45 degree
Note that the zero values will be stored when the calibrate button is pressed. You can calibrate the sensor at an inclination of say 30 degree in roll and it will show you a roll of 0 whenever the sensor is inclined at 30 degree.
LCD Module
As mentioned we will be using a standard LCD module and thankfully we don’t have to do all that awful wiring, just mount the LCD on the pins provided on development stick and you are good to go. Don’t forget to adjust the contrast pot which sits on the board.
Interfacing an LCD is pretty straightforward and standard task and so not explained here. LCD is being run in 4 bit mode.
System Design and Assembling
System Block Diagram
Fig. 6: Block Diagram of ATMega168 based Digital Spirit Level Indicator
The entire setup is presented in the diagram above. The ATmega168 Development Stick reads the ADC values from the accelerometer and converts them into roll / pitch values; these are then displayed on the LCD. The MCU also monitors the status of the calibrate switch, if pressed, it obtains 10 samples from each axis, averages and stores them as the zero values in EEPROM. These are then used for further computation. An optional LED is used to indicate that the code is working fine, it just blinks away.
Circuit Diagram
The circuit is designed around the ATmega168 development stick. The VCC signal from the stick is 5V and is used to power the LCD and is also converted to 3.3V for the accelerometer using the LM1117 voltage regulator.
Now all that remains is the firmware, which shall be reviewed next.
Fig. 7: Flow Chart of C Code for Spirit Level Indicator
Figure 6 shows high level flow chart of the firmware program.
Sensor Calibration
Fig. 8: Image showing message on LCD for incorrect calibration of EEPROM
Fig. 9: Image showing message on LCD for correct calibration of EEPROM
A feature added to the design was the sensor calibration. On first boot, the MCU will request the user to calibrate the sensor for zero level before proceeding to displaying the output; this will re-appear if the EEPROM calibration values are corrupt due to any reason. A switch is connected to pin PC2 and whenever it is pressed, the MCU obtains 10 samples from the X-axis and then 10samples from the Y-axis; it averages these individually and stores the resultant as the neutral value for the corresponding axis. This is then used to compute the inclination of the sensor to provide roll/pitch values. To prevent the user from having to calibrate the sensor every time on boot, the calibrated values are stored in EEPROM and are used on boot, unless the user wishes to calibrate the sensor again.
EEPROM Storage
To store the values in EEPROM we make use of the standard AVR EEPROM library. Calibration just averages the ADC values (10 samples for about 4seconds) and uses this as the zero level. When the user calibrates the unit, the X axis offset is stored at address 0x01, which is a 16 bit value; also the Y axis offset is stored at address 0x03, which again is a 16 bit value. To ensure the validity of the data, test bytes are placed at location 0x00 as well as 0x05. Each time on boot; the MCU checks if these test bytes are present, if so it reads the X and Y zero values and uses them for computation, if not it prompts the user to calibrate the sensor before proceeding to normal operation.
Reading Sensor & Computing Output
Fig. 10: Image showing Roll and Pitch values displayed on LCD
As mentioned the sensor values are analog in nature and are read by two ADC channels of the MCU. Since simultaneous reading of multiple channels is not possible an interrupt scheme is employed.
Each time an interrupt occurs, it checks which conversion has been completed, if the X value is obtained, it schedules the conversion of the Y value. Once both are complete it disables the interrupts and signals end of both channel conversion. The main loop then computes and displays the output and clears this flag while also re-enabling interrupts and scheduling X-axis conversion. An averaging filter is implemented to smoothen out the variations in the ADC values, this is not entirely necessary, but reduces the jitter on account of the fast ADC conversion being employed.
Applications
You can use the prototype to check if your table is perfectly leveled. For example, following steps could be useful…
1. Find a flat surface so that we can calibrate the sensor accordingly.
2. Place the prototype on the surface and press the calibrate button. The LCD should display the calibrating screen, which will last for about 4 seconds. Do not move the sensor during this time.
3. After it is done calibrating, the LCD should read roll/pitch of 0 degree. If so, you’re good to go, if not you may want to re-calibrate the sensor.
4. Place the calibrated unit on your desk and check the readings. Is it leveled? If it is, you can play around by tilting the desk and observing how the readings change. If it wasn’t leveled, then get started trying to level the table.
5. Use this to check how leveled any other surface is. You don’t need to go on re-calibrating the sensor when you power on, that’s why we used the EERPOM. You can calibrate the sensor if you want to change the reference angle from 0 degree to any other inclination.
Fig. 11: Image showing Roll and Pitch values displayed on LCD
Circuit Diagrams
Filed Under: Electronic Projects
Questions related to this article?
👉Ask and discuss on EDAboard.com and Electro-Tech-Online.com forums.
Tell Us What You Think!!
You must be logged in to post a comment.