Help with combing code ! - Uni Project

Hi Everyone,

I am doing a project where I am using the 1Sheeld+ and a 2.8 inch TFT Display.

I would like to be able to use the voice recognition from the 1Sheeld+ to display images on the display.

I would like to just use voice recognition to turn on the display by commanding "on" and turn it off by using "off".

I am able an LED to turn on with the On command but the code for the TFT display is more complicated and when I think I have the correct code I'm getting an error that it cannot be compiled to the board.

I would really appreciate any guidance on how I can combine the codes to turn on the display by simply saying on.

Thank you for your help in advance, any advice is greatly appreciated :slight_smile:

Code that turns on display

/*

  this demo can show specified bmp file in root Directory of SD card
  please ensure that your image file is 320x240 size. 

  change __Gnfile_num and __Gsbmp_files to display your image
*/

#include <SD.h>
#include <SPI.h>

#include "LCD.h"
#include "XPT2046.h"

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


const int PIN_SD_CS = 5;                        // pin of sd card

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

unsigned char __Gnbmp_image_offset  = 0;        // offset

int __Gnfile_num = 4;                           // num of file

char __Gsbmp_files[4][FILENAME_LEN] =           // add file name here
{
"flower.bmp",
"tiger.bmp",
"tree.bmp",
"ali.bmp",
};

File bmpFile;

void setup()
{
    Serial.begin(9600);
    
    __XPT2046_CS_DISABLE();
    
    pinMode(PIN_SD_CS,OUTPUT);
    digitalWrite(PIN_SD_CS,HIGH);
    Sd2Card card;
    card.init(SPI_FULL_SPEED, PIN_SD_CS); 
    if(!SD.begin(PIN_SD_CS))  { 
        Serial.println("SD init failed!");
        while(1);                               // init fail, die here
    }
    
    SPI.setDataMode(SPI_MODE3);
    SPI.setBitOrder(MSBFIRST);
    SPI.setClockDivider(SPI_CLOCK_DIV2);
    SPI.begin();
    
    Tft.lcd_init();
    Tft.lcd_display_string(50, 120, (const uint8_t *)"Starting to display...", FONT_1608, RED);
    Serial.println("SD OK!");
    delay(1000);
}

void loop()
{
    for(unsigned char i=0; i<__Gnfile_num; i++) {
        bmpFile = SD.open(__Gsbmp_files[i]);
        if (! bmpFile) {
            Serial.println("image not found");
            while (1);
        }
        
        if(! bmpReadHeader(bmpFile)) {
            Serial.println("bad bmp");
            return;
        }

        bmpdraw(bmpFile, 0, 0);
        bmpFile.close();
        delay(1000);
        delay(1000);
        delay(1000);
        delay(1000);
    }
}

/*********************************************/
// 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;
            }
            
            Tft.lcd_set_cursor(offset_x, i);
	    Tft.lcd_write_byte(0x22, LCD_CMD);
            __LCD_DC_SET();
	    __LCD_CS_CLR();
	    for (int m = 0; m < BUFFPIXEL; m ++) {
	        __LCD_WRITE_BYTE(__color[m] >> 8);
		__LCD_WRITE_BYTE(__color[m] & 0xFF);
	    }
	    __LCD_CS_SET();
        }
    }
    
    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;
}

Code for turning on LED with voice recognition

#define CUSTOM_SETTINGS
#define INCLUDE_VOICE_RECOGNIZER_SHIELD
#define INCLUDE_MUSIC_PLAYER_SHIELD
#define INCLUDE_TERMINAL_SHIELD

/* Include 1Sheeld library. */
#include <OneSheeld.h>

/* Voice commands set by the user. */
const char onCommand[] = "on";
const char offCommand[] = "off";

int led = 13;

void setup()
{
  /* Start Communication. */
  OneSheeld.begin();
  /* Error Commands handiling. */
  VoiceRecognition.setOnError(error);
  
  VoiceRecognition.start();
  pinMode (led, OUTPUT);
}

void loop () 
{
  /* Check if new command received. */
  if(VoiceRecognition.isNewCommandReceived())
  {
    /* Compare the on command. */
    if(!strcmp(onCommand,VoiceRecognition.getLastCommand()))
    {
      /* turn on led. */
      digitalWrite (led, HIGH);
    }
    /* Compare the off command. */
    else if (!strcmp(offCommand,VoiceRecognition.getLastCommand()))
    {
      /* turn off led */
      digitalWrite (led, LOW);
    }
   
  }
}

/* Error checking function. */
void error(byte errorData)
{
  /* Switch on error and print it on the terminal. */
  switch(errorData)
  {
    case NETWORK_TIMEOUT_ERROR: Terminal.println("Network timeout");break;
    case NETWORK_ERROR: Terminal.println("Network Error");break;
    case AUDIO_ERROR: Terminal.println("Audio error");break;
    case SERVER_ERROR: Terminal.println("No Server");break;
    case SPEECH_TIMEOUT_ERROR: Terminal.println("Speech timeout");break;
    case NO_MATCH_ERROR: Terminal.println("No match");break;
    case RECOGNIZER_BUSY_ERROR: Terminal.println("Busy");break;
  }
}

VoiceRecognition_LED_on_off.ino (1.94 KB)

displayon.ino (5.15 KB)

JordanHam:
I'm getting an error that it cannot be compiled to the board.

When you encounter an error you'll see a button on the right side of the orange bar "Copy error messages". Click that button. Paste the error in a message here USING CODE TAGS (</> button on the toolbar).

Arduino: 1.6.8 (Windows 10), Board: "Arduino/Genuino Uno"

sketch\Turn_on_display_with_voice.ino.cpp.o: In function `error(unsigned char)':

C:\Users\Jordanham1994\Desktop\Arduino\my attempts\Turn_on_display_with_voice/Turn_on_display_with_voice.ino:183: undefined reference to `Terminal'

C:\Users\Jordanham1994\Desktop\Arduino\my attempts\Turn_on_display_with_voice/Turn_on_display_with_voice.ino:183: undefined reference to `Terminal'

collect2.exe: error: ld returned 1 exit status

exit status 1
Error compiling for board Arduino/Genuino Uno.

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

Please post your full Turn_on_display_with_voice sketch. If possible you should always post code directly in the forum thread as text using code tags (</> button on the toolbar). This will make it easy for anyone to look at it, which will increase the likelihood of you getting help. If the sketch is longer than the forum will allow then it's ok to add it as an attachment. Don't put your code in some external file service like dropbox, etc. We shouldn't need to go to an external website just to help you. I do feel it's reasonable to post a link to code hosted on GitHub or similar code hosting sites since that's an platform specifically designed for this sort of thing

Please always do a Tools > Auto Format on your code before posting it. This will make it easier for you to spot bugs and make it easier for us to read. If you're using the Arduino Web Editor then you will not have access to this useful tool. I recommend using the standard Arduino IDE instead.

When your code requires a library that's not included with the Arduino IDE please post a link(using the chain links icon on the toolbar to make it clickable) to where you downloaded that library from or if you installed it using Library Manger(Sketch > Include Library > Manage Libraries) then say so and state the full name of the library.

Thank you for your help Pert! I'm new to the community and have only ever done quite simple things with the Arduino. But thanks for your advice I'll remember to do that next time. I have also added the codes to my original post.

As requested please find my attempt below. (It's probably a mess as I am almost clueless on how I would combine this type of code) I also understand that not all of the code is necessary but any help would be appreciated.

<OneSheeld.h> 1Sheeld - All Arduino shields on your Smartphone
<SD.h> and others https://www.waveshare.com/wiki/2.8inch_TFT_Touch_Shield#Arduino_Demo

/#include <OneSheeld.h> 

#include <SD.h>
#include <SPI.h>

#include "LCD.h"
#include "XPT2046.h"


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

#define CUSTOM_SETTINGS
#define INCLUDE_VOICE_RECOGNIZER_SHIELD




/* Voice commands set by the user. */
const char onCommand[] = "on";
const char offCommand[] = "off";
const int PIN_SD_CS = 5;                        // pin of sd card

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

unsigned char __Gnbmp_image_offset  = 0;        // offset

int __Gnfile_num = 4;                           // num of file

char __Gsbmp_files[4][FILENAME_LEN] =           // add file name here
{
  "flower.bmp",
  "tiger.bmp",
  "tree.bmp",
  "ali.bmp",
};

File bmpFile;

void setup()

{

  /* Check if new command received. */
  if (VoiceRecognition.isNewCommandReceived())
  {
    /* Compare the on command. */
    if (!strcmp(onCommand, VoiceRecognition.getLastCommand()))
    {
      /* turn on led. */
      digitalWrite (PIN_SD_CS, HIGH);
    }
    /* Compare the off command. */
    else if (!strcmp(offCommand, VoiceRecognition.getLastCommand()))
    {
      /* turn off display */
      digitalWrite (PIN_SD_CS, LOW);
    }

  }
  /* Start Communication. */
  OneSheeld.begin();
  /* Error Commands handiling. */
  VoiceRecognition.setOnError(error);

  VoiceRecognition.start();
  Serial.begin(9600);

  __XPT2046_CS_DISABLE();

  pinMode(PIN_SD_CS, OUTPUT);
  digitalWrite(PIN_SD_CS, HIGH);
  Sd2Card card;
  card.init(SPI_FULL_SPEED, PIN_SD_CS);
  if (!SD.begin(PIN_SD_CS))  {
    Serial.println("SD init failed!");
    while (1);                              // init fail, die here
  }

  SPI.setDataMode(SPI_MODE3);
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV2);
  SPI.begin();

  Tft.lcd_init();
  Tft.lcd_display_string(50, 120, (const uint8_t *)"Starting to display...", FONT_1608, RED);
  Serial.println("SD OK!");
  delay(1000);
}

void loop()
{
  for (unsigned char i = 0; i < __Gnfile_num; i++) {
    bmpFile = SD.open(__Gsbmp_files[i]);
    if (! bmpFile) {
      Serial.println("image not found");
      while (1);
    }

    if (! bmpReadHeader(bmpFile)) {
      Serial.println("bad bmp");
      return;
    }

    bmpdraw(bmpFile, 0, 0);
    bmpFile.close();
    delay(1000);
    delay(1000);
    delay(1000);
    delay(1000);
  }
}

/*********************************************/
// 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;
      }

      Tft.lcd_set_cursor(offset_x, i);
      Tft.lcd_write_byte(0x22, LCD_CMD);
      __LCD_DC_SET();
      __LCD_CS_CLR();
      for (int m = 0; m < BUFFPIXEL; m ++) {
        __LCD_WRITE_BYTE(__color[m] >> 8);
        __LCD_WRITE_BYTE(__color[m] & 0xFF);
      }
      __LCD_CS_SET();
    }
  }

  Serial.print(millis() - time, DEC);
  Serial.println(" ms");
}

/* Error checking function. */
void error(byte errorData)
{
  /* Switch on error and print it on the terminal. */
  switch (errorData)
  {
    case NETWORK_TIMEOUT_ERROR: Terminal.println("Network timeout"); break;
    case NETWORK_ERROR: Terminal.println("Network Error"); break;
    case AUDIO_ERROR: Terminal.println("Audio error"); break;
    case SERVER_ERROR: Terminal.println("No Server"); break;
    case SPEECH_TIMEOUT_ERROR: Terminal.println("Speech timeout"); break;
    case NO_MATCH_ERROR: Terminal.println("No match"); break;
    case RECOGNIZER_BUSY_ERROR: Terminal.println("Busy"); break;
  }
}

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;
}

The problem is with this line:

/#include <OneSheeld.h>

You accidentally added the slash. Change it to this:

#include <OneSheeld.h>

After that the next problem you will encounter is that the compiled size exceeds the program storage space of your Uno, a more difficult problem to resolve. The easiest solution would be to upgrade from your Uno to an Arduino Mega board. I don't see any obvious low hanging fruit for reducing the program memory usage of your sketch. I did find reducing the value of BUFFPIXEL and BUFFPIXEL_X3 to help a bit.

Thanks again Pert! That was helpful! I noticed yesterday about the sketch being too big for the uno board. I have obtained a mega board and fixed the code from what you have mentioned. However, the display is not turning on from my attempt of code. Is there any part of the code that you can see that might be stopping this?

What happens if you run the Arduino/DisplayString/DisplayString.ino example sketch that came with the download from https://www.waveshare.com/wiki/2.8inch_TFT_Touch_Shield#Arduino_Demo?

If I run the displaystring.ino code it turns the screen on and displays Hello , world! 2.8" TFT Touch Shield"

the code used is

#include <stdint.h>
#include <LCD.h>
#include <SPI.h>
#define __AVR_ATmega32U4__

void setup()
{  
    SPI.setDataMode(SPI_MODE3);
    SPI.setBitOrder(MSBFIRST);
    SPI.setClockDivider(SPI_CLOCK_DIV4);
    SPI.begin();
    
    Tft.lcd_init();                                      // init TFT library
    Tft.lcd_display_string(60, 120, (const uint8_t *)"Hello, world !", FONT_1608, RED);
    Tft.lcd_display_string(30, 152, (const uint8_t *)"2.8' TFT Touch Shield", FONT_1608, RED);
}

void loop()
{
  
}

I have also uploaded the code when having the display on top of the 1sheeld. This just has a blank white screen on the display.