Попытка использовать акселерометр 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();
  }
}

, 👍1


1 ответ


1

Ваш SPI не настроен для Arduino UNO. Проверьте другой пример для SPI, и вы будете использовать контакты 11 и 13, это обязательно и 8,9,10 или любые три, и для этих 3 контактов есть определение - посмотрите пример для вашего дисплея. Для I2C есть ли у вас съемные резисторы на обеих линиях I2C от 4,7 К до 10 К? Это необходимо. Удачи

,

Извините, я должен был уточнить немного больше, чем указано в коде, я использую контакты 11 и 13 для SPI, игнорируя настройку, определенную в начале кода. Существует два оператора объявления для дисплея - один использует любую комбинацию контактов для дисплея, а другой использует 11 и 13 плюс три других. Что касается подтягивающих резисторов, нет, я их не вставлял. Однако я подумал, что если датчик работал, когда был запущен его собственный пример кода (даже без резисторов), то он должен работать вместе с дисплеем. Или мне не хватает какого-то вмешательства?, @Tom W