I'm trying to stream the data coming from my I2C MMA8452Q accelerometer to an Adafruit-based SSD1351 OLED RGB display that uses SPI via an Arduino UNO.
When I run example code for the accelerometer I can see it outputting data to the serial monitor, and when I run my code for the screen using a joystick as test input it graphs the values nicely.
When I try and build in the I2C example code into my code for the display, the moment I include to the code to read the values from the accelerometer, the program runs setup and then goes blank after that. When I block out the sensor read and swap in the joystick reads it works fine again.
I've been staring at all kinds of forum posts about using SPI and I2C simultaneously but I haven't really found any with a straightforward solution or they use a very different board.
#include <Adafruit_SSD1351.h>
#include <SparkFun_MMA8452Q.h>
#include <SPI.h>
#include <Wire.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 128 // Change this to 96 for 1.27" OLED.
// You can use any (4 or) 5 pins
#define SCLK_PIN 2 // not using this as I've got it setup
#define MOSI_PIN 3 // on the hardware SPI pins as per the text below
#define DC_PIN 4
#define CS_PIN 5
#define RST_PIN 6 // not in use
#define joy_XPin A1
#define joy_YPin A0
// Color definitions
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
// Option 1: use any pins but a little slower
// Adafruit_SSD1351 tft = Adafruit_SSD1351(SCREEN_WIDTH, SCREEN_HEIGHT, CS_PIN, DC_PIN, MOSI_PIN, SCLK_PIN, RST_PIN);
// Option 2: must use the hardware SPI pins
// (for UNO thats sclk = 13 and sid(which is SDA on my display) = 11) and pin 10 must be
// an output. This is much faster - also required if you want
// to use the microSD card (see the image drawing example)
Adafruit_SSD1351 tft = Adafruit_SSD1351(SCREEN_WIDTH, SCREEN_HEIGHT, &SPI, CS_PIN, DC_PIN, RST_PIN);
MMA8452Q accel; // intialise sensor - SDA/SCL connected to A4/A5 pins as per example code
#define graphLength 32
int joy_X, joy_Y;
int tilt_X, tilt_Y;
int graphY[graphLength] = {0};
int graphX[graphLength] = {0};
void setup() {
Serial.begin(9600);
tft.begin();
Wire.begin();
tft.fillScreen(BLACK);
tft.setCursor(10,64);
tft.setTextColor(WHITE);
tft.println("Welcome, have fun");
delay(2000);
tft.fillScreen(BLACK);
}
void loop() {
// scaled inputs to be smaller and offset to be in the middle of the screen
joy_X = (analogRead(joy_XPin) / 32)+48;
joy_Y = (analogRead(joy_YPin) / 32)+48;
// when this block is included everything breaks
// this is the code to read the accelerometer input so I'm pretty sure the issue is here.
/*
if(accel.available()){
tilt_X = accel.getCalculatedX() * 10;
tilt_Y = accel.getCalculatedY()* 10;
}
*/
graphY[graphLength - 1] = tilt_X; // swap tilt_X/Y with joy_X/Y to graph joystick inputs
graphX[graphLength - 1] = tilt_Y;
for(int i = 0; i <= (graphLength - 1); i++){ // invokes undefined behaviour but it works for now
tft.drawPixel(i,graphY[i],RED);
tft.drawPixel(i,graphX[i],BLUE);
}
delay(5);
graphShiftAlong();
}
// Just functions to clear the things I've drawn on the display rather than trying to wipe the whole display each time.
void clearPixel(uint16_t x, uint16_t y){
tft.drawPixel(x, y, BLACK);
}
void drawRect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color){
int x1,y1,x2,y2;
w = w/2;
h = h/2;
x1 = x - w;
y1 = y - h;
x2 = x + w;
y2 = y + h;
tft.drawLine(x1,y1,x1,y2,color); // top left to bottom left
tft.drawLine(x1,y1,x2,y1,color); // top left to top right
tft.drawLine(x2,y1,x2,y2,color); // top right to bottom right
tft.drawLine(x2,y2,x1,y2,color); // bottom right to bottom left
}
void clearRect(uint16_t x, uint16_t y, uint16_t w, uint16_t h){
drawRect(x,y,w,h,BLACK);
}
// Sets the 'old' data to be drawn as black and redraws it one pixel offset
// Compiler gives me red text but not errors so I'm running with it for now
void graphShiftAlong(){
for(int i = 0; i <= (graphLength - 1); i++){
tft.drawPixel(i,graphY[i],BLACK);
tft.drawPixel(i,graphX[i],BLACK);
graphX[i] = graphX[i+1];
graphY[i] = graphY[i+1];
}
}
The example code I'm using for the sensor is here:
Library for the MMA8452Q
By: Jim Lindblom and Andrea DeVore
SparkFun Electronics
Do you like this library? Help support SparkFun. Buy a board!
https://www.sparkfun.com/products/14587
This sketch uses the SparkFun_MMA8452Q library to initialize
the accelerometer and stream calcuated x, y, z, acceleration
values from it (in g units).
Hardware hookup:
Arduino --------------- MMA8452Q Breakout
3.3V --------------- 3.3V
GND --------------- GND
SDA (A4) --\/330 Ohm\/-- SDA
SCL (A5) --\/330 Ohm\/-- SCL
The MMA8452Q is a 3.3V max sensor, so you'll need to do some
level-shifting between the Arduino and the breakout. Series
resistors on the SDA and SCL lines should do the trick.
License: This code is public domain, but if you see me
(or any other SparkFun employee) at the local, and you've
found our code helpful, please buy us a round (Beerware
license).
Distributed as is; no warrenty given.
*/
#include <Wire.h> // Must include Wire library for I2C
#include "SparkFun_MMA8452Q.h" // Click here to get the library: http://librarymanager/All#SparkFun_MMA8452Q
MMA8452Q accel; // create instance of the MMA8452 class
void setup() {
Serial.begin(9600);
Serial.println("MMA8452Q Basic Reading Code!");
Wire.begin();
if (accel.begin() == false) {
Serial.println("Not Connected. Please check connections and read the hookup guide.");
while (1);
}
}
void loop() {
if (accel.available()) { // Wait for new data from accelerometer
// Acceleration of x, y, and z directions in g units
Serial.print(accel.getCalculatedX(), 3);
Serial.print("\t");
Serial.print(accel.getCalculatedY(), 3);
Serial.print("\t");
Serial.print(accel.getCalculatedZ(), 3);
Serial.println();
}
}
1 Answer 1
Your SPI is not setup for the Arduino UNO. Check another example for SPI and you will be using pins 11 and 13, this is mandatory and 8,9,10 or any three and there is a definition statement for these 3 pins - look at the example for your display. For I2C do you have pullup resistors on both I2C lines 4.7k up to 10k? These are required. Good luck
-
Sorry I should have clarified a bit more than what is in the code, I am using pins 11 and 13 for SPI, ignoring the setup defined early in the code. There are two declaration statements for the display - one uses any combination of pins for the display and the other uses 11 and 13 plus the other three. As for the pullup resistors, no I haven't put those in. However I did think that if the sensor worked when its own example code was run (even without the resistors) that it should run in conjunction with the display. Or is there some interference I am missing?Tom W– Tom W2021年07月03日 00:22:04 +00:00Commented Jul 3, 2021 at 0:22
Explore related questions
See similar questions with these tags.