Попытка использовать акселерометр I2C и SPI OLED
Я пытаюсь передать данные, поступающие с моего акселерометра I2C MMA8452Q, на OLED RGB-дисплей SSD1351 на базе Adafruit, который использует SPI через Arduino UNO.
Когда я запускаю пример кода для акселерометра, я вижу, как он выводит данные на последовательный монитор, а когда я запускаю свой код для экрана, используя джойстик в качестве тестового ввода, он красиво отображает значения.
Когда я пытаюсь встроить пример кода I2C в свой код для дисплея, в тот момент, когда я включаю код для считывания значений с акселерометра, программа запускает настройку, а затем гаснет после этого. Когда я блокирую показания датчика и меняю местами показания джойстика, он снова работает нормально.
Я просматривал всевозможные сообщения на форуме об одновременном использовании SPI и I2C, но на самом деле не нашел ни одного простого решения, или они используют совсем другую плату.
#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];
}
}
Пример кода, который я использую для датчика, находится здесь:
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();
}
}
@Tom W, 👍1
1 ответ
Ваш SPI не настроен для Arduino UNO. Проверьте другой пример для SPI, и вы будете использовать контакты 11 и 13, это обязательно и 8,9,10 или любые три, и для этих 3 контактов есть определение - посмотрите пример для вашего дисплея. Для I2C есть ли у вас съемные резисторы на обеих линиях I2C от 4,7 К до 10 К? Это необходимо. Удачи
- OVF в последовательном мониторе вместо данных
- Последовательная связь между несколькими устройствами (или ардуино)
- Использование MPU-6050 без I2C
- Проблема с настройкой i2c OLED wemos D1 mini shiled (64*24)
- Arduino UNO несовместимо с чтением регистра I2C из ArduCam
- ADXL345 выдает ошибку проводки в режиме SPI
- MPU-6050 с Arduino – вскрытие
- DHT20 и дисплей Oled не работают вместе
Извините, я должен был уточнить немного больше, чем указано в коде, я использую контакты 11 и 13 для SPI, игнорируя настройку, определенную в начале кода. Существует два оператора объявления для дисплея - один использует любую комбинацию контактов для дисплея, а другой использует 11 и 13 плюс три других. Что касается подтягивающих резисторов, нет, я их не вставлял. Однако я подумал, что если датчик работал, когда был запущен его собственный пример кода (даже без резисторов), то он должен работать вместе с дисплеем. Или мне не хватает какого-то вмешательства?, @Tom W