-
Notifications
You must be signed in to change notification settings - Fork 6
Nucleo Accel Starter Project
The purpose of this starter project is to guide you through being able to get readings from the ADXL343 accelerometer over the I2C bus on a Nucleo.
- Nucleo STM32F303RE
- ADXL343 accelerometer
- At least 5 solid core female-female wires
- 1 USB A to mini B cable
ADXL343 accelerometer datasheet
Nucleos come with a removable ST-Link debugger/programmer integrated on the board, allowing extensive debugging options through a simple USB connection. STM32 MCU have a wide range of hardware capabilities, with dedicated internal circuitry for I2C, SPI, UART, timers, and more. Read this for more information.
The ADXL343 is a digital accelerometer that you’ll be using today. This device measures acceleration in all the x, y and z axes and sends this data via a serial line using the I2C communication protocol.
I2C offers two-way communication between a device such as the ADXL343 (slave) and the Nucleo (master). Notice the SDA (Serial Data) and SCL (Serial Clock) pins on both the accelerometer and the Nucleo.
I2C relies on the clock line (SCL) to keep time between the devices connected so that they can communicate at the same rate. The data line (SDA) is a shared data line between the devices.
Each device enabled with I2C also has an address. Try to find the address for the ADXL343 accelerometer in the datasheet.
Read this if you want to learn more about I2C.
Nucleo Pin 20 (GND) --> Accelerometer GND: The GND (ground) cable is your negative power terminal.
Nucleo Pin 16 (3V3) --> Accelerometer VIN: The VIN (voltage in) cable is your positive power terminal.
Nucleo Pin 16 (3V3) --> Accelerometer CS: The CS pin on the accelerometer must be tied high to Vdd in order to use I2C. You can use the arduino-type 3V3 output on the nucleo or use a breadboard.
Nucleo Pin 17 (PA15) --> Accelerometer SCL: The SCL (serial clock) cable is your clock cable.
Nucleo Pin 21 (PB7) --> Accelerometer SDA: The SDA (serial data) cable is your data communication cable.
Refer to the following wiring diagram:
If you have already cloned embedded-testbench for the Servo starter project, you do not need to do it again for the accelerometer.
To get the starter code, open up a new terminal window, clone the embedded test bench repository, and make a nucleo tutorial branch
$ git clone https://github.com/umrover/embedded-testbench/
(if not already cloned)
$ cd embedded-testbench
$ git checkout starter-projects
$ git checkout -b starter/<name>
\
Open up the Cube IDE project by opening the folder and double clicking on the .project file. Make sure that you already have Cube IDE installed.
A register is a location on a device such as the accelerometer that one can access data from or send commands to. We will be both writing to and reading from the accelerometer's registers. We will write to registers in order to set up the accelerometer for usage. We will read from registers which hold the acceleration data we are looking for. Descriptions of each register (what data you can read, or what you can do by writing to it) can be found on the datasheet.
A master device can have multiple slaves. Therefore, each slave device needs a distinct address which the master can use to select the correct device to communicate with over the I2C bus.
The accelerometer I2C address and registers we will need to write to and read from are summarized here. Both device addresses and register locations are typically written in hexadecimal.
Useful addresses and registers. These come from the adxl343 datasheet.
We may have to work with data values which are many bytes long. However, sometimes we are restricted to working with just one byte at a time. Therefore, we split large data values into "most significant" and "least significant" bytes.
The accelerometer returns acceleration values for each axis as a two-byte number. However, each byte of a single reading is stored in a separate register on the accelerometer, so we must read them separately and combine the two numbers. Since we are dealing with binary numbers, we can accomplish this using bitwise operations, such as bitwise left shift (<<) and bitwise OR (|).
As a decimal analogy to this, imagine you have the number 2048. In MSB/LSB format it could be split up as 20 and 48. In order to combine the two correctly, you have to shift 20 over 2 decimal places (multiply by 10^2) and then add it to 48. When it comes to retrieving and combining the data of the MSB and LSB registers, the idea is the same.
Splitting the data to be sent in two registers allows for higher precision data to be sent. More in depth info.
For writing to and reading data from registers, some functions are provided to you.
If you look inside the main.c, you'll see that long read_byte_data(uint8_t addr, char cmd)
and
void write_byte_data(uint8_t addr, char cmd, uint8_t data)
are provided to you.
The first step of this project is to write to the accelerometer's power&sleep register and get it out of sleep mode.
We must use the void write_byte_data(uint8_t addr, char cmd, uint8_t data)
function for this.
As implied by the parameters of the function, we must know three things:
- the i2c address of the accelerometer
- the hexidecimal value of the register we want to write to (or sometimes it is called the command)
- the hexidecimal value we want to set that register to be
The i2c address of the device can be found in the datasheet listed as 'i2c address'. Take a look at page 16 in the datasheet.
For our use case, the ALT ADDRESS pin is grounded.
The register we want to write to is the power&sleep register.
Take a look at page 23 of the datasheet under 'POWER_CTL(Read/Write)'.
Listed next to it is 0x2D, which is the hex value of the register we want to write to.
How do you know what hexadecimal data to set that register to be? You have to take a further look at the register.
This is a picture from the datasheet. It shows us that register 0x2D is an 8 bit register, and labels each bit.
Below this on page 26/27 of the datasheet is a description of each bit, and what setting it to be a 0 or 1 means.
To summarize:
Bits 7 and 6 are automatically set to be zeros.
Bit 5, the Link bit, has to do with interrupts, which we are not using so it can be set to 0.
Bit 4, the AUTO_SLEEP bit, automatically puts the device into sleep mode if it detects inactivity. It says if the link bit is a zero this bit must also be set to 0.
Below is a description of bit 3, the Measure bit.
According to the description, in order to place the accelerometer into measurement mode, we need to set that bit to 1.
Bit 2, the Sleep bit, puts the device into sleep mode if it is set to 1, so we want to set this to 0.
Bits 1 and 0, the Wakeup bits control the frequency of readings in sleep mode, which is off, so we can leave these as 00 (since there are two of them).
More in depth descriptions are in the datasheet.
Overall, this gives us a bit string of 00001000
which is what we want to set the register to be.
For ease of readability we usually send this over as a base 16 hexidecimal value.
Our bit string is currently in binary (base 2) so we need to convert it to base 16. Here is a good online converter for going from binary to hex. Go ahead and use that calculator to convert the binary string to hex. A thing to note about hex values is that they are all prefixed by 0x
.
With these three pieces of information we can now enable the accelerometer. Using write_byte_data you can do this in your accelerometer code like so:
write_byte_data(i2c_dev_address, <insert register to write to>, <insert hex value to set register to>);
.
Initialize the sensor, and read x, y, and z data from it. The starter code along with this tutorial has some hints on what to do. Make sure you're taking a close look at the datasheet and all the registers to verify that you are turning the accelerometer on with all the correct bits set in the relevant registers, having it read data correctly, and for what values you need for unit conversions to m/s^2. Feel free to reach out to the ESW lead or other returning members for guidance!
Before you test your code you will want to see that it can 'compile' by building the project. If there are any errors, fix them.
Because in this tutorial we do not print the data anywhere, we will have to use the debugger to investigate whether or not the code is working properly. This is good practice for what you may expect to see in the future.
Make sure that your Nucleo is connected to your computer. Also make sure that your project is able to build.
Click on Run -> Debug As -> 1 STM32 C/C++ Application.
On the following screen, you can just press OK.
If your device is unable to detect the Nucleo connected to it, you may see the following screen.
Retry the previous steps and if that does not work, then either double check your connections, or seek a new Nucleo board.
In the future, you may be able to get away with just clicking on Run -> Debug, or using the keyboard shortcut F11. This does not work the first time if you have never clicked on the Debug As button.
Now that you're in the debug mode, you may set breakpoints and run through your code or pause at any given moment. When paused, we can also see the values of certain variables. We will use this feature to view if the data we are reading for our accelerometer is reasonable.
TODO - Add to the wiki of how to set breakpoints and read variables..
You have completed the Accelerometer on Nucleo Starter Project! Contact the ESW lead for further instructions.