TFT Display and QMC5883L Issue

Hi Guys,

Hope your having a good New Year.

I have started a new project which involves a 3.8" TFT screen, an arduino Uno and a QMC5883L compass sensor.

The issue i'm having is once the "Compass();" line in the for loop is run the screen goes white. it should have turned blue and started counting. does anyone know how to get the compass() to execute and continue the for loop?

Thank you for the help and have a good day.

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_TFTLCD.h> // Hardware-specific library
#include <SD.h>
#include <SPI.h>

//For Mag Sensor
#include <Wire.h>
#include <MechaQMC5883.h>
MechaQMC5883 qmc;
int Test;


#define LCD_CS A3 // Chip Select goes to Analog 3
#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0
#define PIN_SD_CS 10 // Adafruit SD shields and modules: pin 10

#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin


//   D0 connects to digital pin 8  (Notice these are
//   D1 connects to digital pin 9   NOT in order!)
//   D2 connects to digital pin 2
//   D3 connects to digital pin 3
//   D4 connects to digital pin 4
//   D5 connects to digital pin 5
//   D6 connects to digital pin 6
//   D7 connects to digital pin 7
// For the Arduino Mega, use digital pins 22 through 29
// (on the 2-row header at the end of the board).

// Assign human-readable names to some common 16-bit color values:
#define  BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
// If using the shield, all control and data lines are fixed, and
// a simpler declaration can optionally be used:
// Adafruit_TFTLCD tft;


#define MAX_BMP         10                      // bmp file num
#define FILENAME_LEN    20                      // max file name length

const int __Gnbmp_height = 320;                 // bmp hight
const int __Gnbmp_width  = 240;                 // bmp width

unsigned char __Gnbmp_image_offset  = 0;        // offset

int __Gnfile_num = 2;                           // num of file

char __Gsbmp_files[2][FILENAME_LEN] =           // add file name here
{
"flower.bmp",
//"tiger.bmp",
"tree.bmp",
//"RedRose.bmp",
};
File bmpFile;

/*********************************************/
// This procedure reads a bitmap and draws it to the screen
// its sped up by reading many pixels worth of data at a time
// instead of just one pixel at a time. increading the buffer takes
// more RAM but makes the drawing a little faster. 20 pixels' worth
// is probably a good place

#define BUFFPIXEL       60                      // must be a divisor of 240 
#define BUFFPIXEL_X3    180                     // BUFFPIXELx3

void bmpdraw(File f, int x, int y)
{
    bmpFile.seek(__Gnbmp_image_offset);

    uint32_t time = millis();

    uint8_t sdbuffer[BUFFPIXEL_X3];                 // 3 * pixels to buffer

    for (int i=0; i< __Gnbmp_height; i++) {
        for(int j=0; j<(240/BUFFPIXEL); j++) {
            bmpFile.read(sdbuffer, BUFFPIXEL_X3);
            
            uint8_t buffidx = 0;
            int offset_x = j*BUFFPIXEL;
            unsigned int __color[BUFFPIXEL];
            
            for(int k=0; k<BUFFPIXEL; k++) {
                __color[k] = sdbuffer[buffidx+2]>>3;                        // read
                __color[k] = __color[k]<<6 | (sdbuffer[buffidx+1]>>2);      // green
                __color[k] = __color[k]<<5 | (sdbuffer[buffidx+0]>>3);      // blue
                
                buffidx += 3;
            }

      for (int m = 0; m < BUFFPIXEL; m ++) {
              tft.drawPixel(m+offset_x, i,__color[m]);
      }
        }
    }
    
    Serial.print(millis() - time, DEC);
    Serial.println(" ms");
}

boolean bmpReadHeader(File f) 
{
    // read header
    uint32_t tmp;
    uint8_t bmpDepth;
    
    if (read16(f) != 0x4D42) {
        // magic bytes missing
        return false;
    }

    // read file size
    tmp = read32(f);
    Serial.print("size 0x");
    Serial.println(tmp, HEX);

    // read and ignore creator bytes
    read32(f);

    __Gnbmp_image_offset = read32(f);
    Serial.print("offset ");
    Serial.println(__Gnbmp_image_offset, DEC);

    // read DIB header
    tmp = read32(f);
    Serial.print("header size ");
    Serial.println(tmp, DEC);
    
    int bmp_width = read32(f);
    int bmp_height = read32(f);
    
    if(bmp_width != __Gnbmp_width || bmp_height != __Gnbmp_height)  {    // if image is not 320x240, return false
        return false;
    }

    if (read16(f) != 1)
    return false;

    bmpDepth = read16(f);
    Serial.print("bitdepth ");
    Serial.println(bmpDepth, DEC);

    if (read32(f) != 0) {
        // compression not supported!
        return false;
    }

    Serial.print("compression ");
    Serial.println(tmp, DEC);

    return true;
}

/*********************************************/
// These read data from the SD card file and convert them to big endian
// (the data is stored in little endian format!)

// LITTLE ENDIAN!
uint16_t read16(File f)
{
    uint16_t d;
    uint8_t b;
    b = f.read();
    d = f.read();
    d <<= 8;
    d |= b;
    return d;
}

// LITTLE ENDIAN!
uint32_t read32(File f)
{
    uint32_t d;
    uint16_t b;

    b = read16(f);
    d = read16(f);
    d <<= 16;
    d |= b;
    return d;
}

void setup(void) {
  //For Mag Sensor
  Wire.begin();
  qmc.init();





  
  Serial.begin(9600);
  Serial.println(F("TFT LCD test"));

#ifdef USE_ADAFRUIT_SHIELD_PINOUT
  Serial.println(F("Using Adafruit 2.4\" TFT Arduino Shield Pinout"));
#else
  Serial.println(F("Using Adafruit 2.4\" TFT Breakout Board Pinout"));
#endif

  Serial.print("TFT size is "); Serial.print(tft.width()); Serial.print("x"); Serial.println(tft.height());

  tft.reset();

  uint16_t identifier = tft.readID();
  if(identifier==0x0101)
      identifier=0x9341;
  
  if(identifier == 0x9325) {
    Serial.println(F("Found ILI9325 LCD driver"));
  } else if(identifier == 0x4535) {
    Serial.println(F("Found LGDP4535 LCD driver"));
  }else if(identifier == 0x9328) {
    Serial.println(F("Found ILI9328 LCD driver"));
  } else if(identifier == 0x7575) {
    Serial.println(F("Found HX8347G LCD driver"));
  } else if(identifier == 0x9341) {
    Serial.println(F("Found ILI9341 LCD driver"));
  } else if(identifier == 0x8357) {
    Serial.println(F("Found HX8357D LCD driver"));
  } else {
    Serial.print(F("Unknown LCD driver chip: "));
    Serial.println(identifier, HEX);
    Serial.println(F("If using the Adafruit 2.4\" TFT Arduino shield, the line:"));
    Serial.println(F("  #define USE_ADAFRUIT_SHIELD_PINOUT"));
    Serial.println(F("should appear in the library header (Adafruit_TFT.h)."));
    Serial.println(F("If using the breakout board, it should NOT be #defined!"));
    Serial.println(F("Also if using the breakout, double-check that all wiring"));
    Serial.println(F("matches the tutorial."));
    return;
  }
  
  tft.begin(identifier);
  tft.fillScreen(BLUE);
  
  
  
  //Init SD_Card
  pinMode(10, OUTPUT);
   
  if (!SD.begin(10)) {
    Serial.println("initialization failed!");
    tft.setCursor(0, 0);
    tft.setTextColor(WHITE);    
    tft.setTextSize(1);
    tft.println("SD Card Init fail.");   
  }else
  Serial.println("initialization done."); 


// test to see if it will run once
  for(unsigned char i=0; i<__Gnfile_num; i++) {
        bmpFile = SD.open(__Gsbmp_files[i]);
        if (! bmpFile) {
            Serial.println("didnt find image");
            tft.setTextColor(WHITE);    tft.setTextSize(1);
            tft.println("didnt find BMPimage");
            while (1);
        }
   
        if(! bmpReadHeader(bmpFile)) {
            Serial.println("bad bmp");
            tft.setTextColor(WHITE);    tft.setTextSize(1);
            tft.println("bad bmp");
            return;
        }

        bmpdraw(bmpFile, 0, 0);
        bmpFile.close();
        //delay(5000);
        delay(1000);
    }
    tft.fillScreen(BLUE); 
}

int Q;

void Compass(){
  int x, y, z;
  int azimuth;
  qmc.read(&x, &y, &z,&azimuth);
}

void loop(void) {
int x, y, z;


  tft.setTextColor(WHITE);    tft.setTextSize(2);
  for (int R=0; R<=99; R++) {
     Compass();
     Serial.println(R);
     tft.setCursor(20,100); 
     tft.print("Counting test: ");
     tft.println(R);
     delay(1000);
     tft.fillScreen(BLUE);
     //return; 
}

        
    
    
}

Start small. You need to learn how to print to the screen, using the smallest program possible, and use the compass, as two separate projects.

When both are working to your satisfaction and you understand how everything works, combine the projects.

Hi jremington,

Thats what I have done, I have got both codes working perfectly apart. Once they are combined the issues happens. Its this line " qmc.read(&x, &y, &z,&azimuth); " thats the issue I just don't know why.

There are hundreds of lines of pure crap in your code. Get rid of them.
You DO NOT need to read .bmp files in order to print a line of text.

it should have turned blue and started counting

What has that got to do with the compass?

So far, you have not even identified the actual problem.

However, this function won't do anything useful, because nothing is ever returned from it. So, it is difficult to believe that you have successfully used the compass.

void Compass(){
  int x, y, z;
  int azimuth;
  qmc.read(&x, &y, &z,&azimuth);
}

is the compass connected to the SPI port ? if so, does the tftlcd have an SD-card reader on the shield ? iow is there anything else connected to the SPI port ?

Hi jremington,

jremington:
There are hundreds of lines of pure crap in your code. Get rid of them.
You DO NOT need to read .bmp files in order to print a line of text.

I need to print a .bmp for part of the project. I though it was better to give the whole code for people to see then just part of it.

the .bmp was for a launch screen. the final code will do a lot more when its done however I'm starting small.

PS: The compass on a separate code works without issue. See below.

#include <Wire.h>
#include <MechaQMC5883.h>

MechaQMC5883 qmc;

int Test;

//For pushbutton selecting sensitivity
int button = 2;
int select1 = 2;

//For pushbutton set zero
int button1 = 4;
int select2 = 0;



void setup() {
  Wire.begin();
  Serial.begin(9600);
  qmc.init();
  //qmc.setMode(Mode_Continuous,ODR_200Hz,RNG_2G,OSR_256);
  //For pushbutton selecting sensitivity
  pinMode(button, INPUT);
  digitalWrite(button, HIGH); //activate arduino internal pull up
  //For pushbutton set zero
  pinMode(button1, INPUT);
  digitalWrite(button1, HIGH); //activate arduino internal pull up
}

void loop() {
  
//For pushbutton selecting sensitivity
if (digitalRead(button)==LOW){
Serial.println();
Serial.print("Button is pressed: ");
if (select1 < 3){
select1++;
//select1=(select1+1);
Serial.println(select1);
Serial.println();
}  else select1 = 1, Serial.println("1"), Serial.println();
}

  int x, y, z;
  int azimuth;
  //float azimuth; //is supporting float too
  qmc.read(&x, &y, &z,&azimuth);
  //azimuth = qmc.azimuth(&y,&x);//you can get custom azimuth


  if(select1 == 1){
  float Test1 = ((x/200)*(x/200));  // needs to be devided by 100 otherwise number gets to big and goes to negative
  float Test2 = ((y/200)*(y/200));  // needs to be devided by 100 otherwise number gets to big and goes to negative
  float Test3 = ((z/200)*(z/200));  // needs to be devided by 100 otherwise number gets to big and goes to negative
  Test = sqrt(Test1 + Test2 + Test3);  // add all 3 axis numbers together and find there squareroot 
  Serial.print("Low Sensitivity: ");
  Serial.print(Test-select2);  
  Serial.println();
  }


  if(select1 == 2){
  float Test1 = ((x/150)*(x/150));  // needs to be devided by 100 otherwise number gets to big and goes to negative
  float Test2 = ((y/150)*(y/150));  // needs to be devided by 100 otherwise number gets to big and goes to negative
  float Test3 = ((z/150)*(z/150));  // needs to be devided by 100 otherwise number gets to big and goes to negative
  Test = sqrt(Test1 + Test2 + Test3);  // add all 3 axis numbers together and find there squareroot 
  Serial.print("Medium Sensitivity: ");
  Serial.print(Test-select2);  
  Serial.println();
  }

  
  if(select1 == 3){
  float Test1 = ((x/100)*(x/100));  // needs to be devided by 100 otherwise number gets to big and goes to negative
  float Test2 = ((y/100)*(y/100));  // needs to be devided by 100 otherwise number gets to big and goes to negative
  float Test3 = ((z/100)*(z/100));  // needs to be devided by 100 otherwise number gets to big and goes to negative
  Test = sqrt(Test1 + Test2 + Test3);  // add all 3 axis numbers together and find there squareroot 
  Serial.print("High Sensitivity: ");
  Serial.print(Test-select2);  
  Serial.println();
  }

  
//For pushbutton set zero
if (digitalRead(button1)==LOW){
Serial.println();
Serial.print("Button is pressed: ");
select2 = Test;
Serial.println(select2);
Serial.println();
}
 
  delay(1000);
}

Hi Deva_Rishi,

I am using SCL and SDA on Arduino Uno for the compass sensor. Only thing on those pins.

the final code will do a lot more when its done

I'm sure it will, but with your approach that goal is far away.

If you don't yet understand why the Compass() function does nothing useful, you are missing a great deal of desperately needed programming basics.

Hi jremington,

So do you know why Compass() does not work? I can't find anything online that would suggest an issue.

What approach do you suggest?

I stated that Compass() does not return anything. To be more specific, that means the function returns no numbers.

The variables you defined within the function are local variables and go out of scope as soon as the function terminates.

Why did you write this function and what do you want it to do?

That was one attempt I had as it will be used later when expanded. I have also tried

void loop(void) {
int x, y, z;
int azimuth;

  tft.setTextColor(WHITE);    tft.setTextSize(2);
  for (int R=0; R<=99; R++) {
     qmc.read(&x, &y, &z,&azimuth);
     Serial.println(x);
     Serial.println(y);
     Serial.println(z);
     tft.setCursor(20,100); 
     tft.print("Counting test: ");
     tft.println(R);
     delay(1000);
     tft.fillScreen(BLUE);
     //return; 
}

        
    
    
}

Which has had the same effect. Screen goes white, the numbers print to the Adruino IDE serial monitor just not the tft screen.

Thank you for the help.

So, you have not yet learned how to write a simple program to print a line of text, or a number to the TFT screen?

I don't happen to use that particular display (at least not one that uses an Adafruit library), but I've found that reading the documentation and exploring various examples helps a lot.

Come to think of it, you forgot to tell us which display you have. Adafruit doesn't appear to sell a 3.8 inch TFT, so post a link to the product page.

I also suggest to try some experiments, like setting the screen background color to something other than white, or changing the font color to blue, etc.