2

I am using voice command to start/stop display of LDR readings over Arduino. The module I am using is voice module V3. I have downloaded some of its examples. First we need to train the module with specific commands. I have trained it as "on" and "off". Hence I could turn on and off the led using voice command . code:

#include <SoftwareSerial.h>
#include "VoiceRecognitionV3.h"

/**        
  Connection
  Arduino    VoiceRecognitionModule
   2   ------->     TX
   3   ------->     RX
*/
VR myVR(2,3);    // 2:RX 3:TX, you can choose your favourite pins.

uint8_t records[7]; // save record
uint8_t buf[64];
int led = 13;

#define onRecord    (0)
#define offRecord   (1) 

/**
  @brief   Print signature, if the character is invisible, 
           print hexible value instead.
  @param   buf     --> command length
           len     --> number of parameters
*/
void printSignature(uint8_t *buf, int len) {
  int i;
  for(i=0; i<len; i++) {
    if(buf[i]>0x19 && buf[i]<0x7F){
      Serial.write(buf[i]);
    } else {
      Serial.print("[");
      Serial.print(buf[i], HEX);
      Serial.print("]");
    }
  }
}

/**
  @brief   Print signature, if the character is invisible, 
           print hexible value instead.
  @param   buf  -->  VR module return value when voice is recognized.
             buf[0]  -->  Group mode(FF: None Group, 0x8n: User, 0x0n:System
             buf[1]  -->  number of record which is recognized. 
             buf[2]  -->  Recognizer index(position) value of the recognized record.
             buf[3]  -->  Signature length
             buf[4]~buf[n] --> Signature
*/
void printVR(uint8_t *buf) {
  Serial.println("VR Index\tGroup\tRecordNum\tSignature");
  Serial.print(buf[2], DEC);
  Serial.print("\t\t");
  if(buf[0] == 0xFF) {
    Serial.print("NONE");
  } else if(buf[0]&0x80) {
    Serial.print("UG ");
    Serial.print(buf[0]&(~0x80), DEC);
  } else {
    Serial.print("SG ");
    Serial.print(buf[0], DEC);
  }
  Serial.print("\t");
  Serial.print(buf[1], DEC);
  Serial.print("\t\t");
  if(buf[3]>0){
    printSignature(buf+4, buf[3]);
  } else {
    Serial.print("NONE");
  }
  Serial.println("\r\n");
}

void setup() {
  /** initialize */
  myVR.begin(9600);
  Serial.begin(115200);
  Serial.println("Elechouse Voice Recognition V3 Module\r\nControl LED sample");
  pinMode(led, OUTPUT);
  if(myVR.clear() == 0) {
    Serial.println("Recognizer cleared.");
  } else {
    Serial.println("Not find VoiceRecognitionModule.");
    Serial.println("Please check connection and restart Arduino.");
    while(1);
  }
  if(myVR.load((uint8_t)onRecord) >= 0){
    Serial.println("onRecord loaded");
  }
  if(myVR.load((uint8_t)offRecord) >= 0){
    Serial.println("offRecord loaded");
  }
}

void loop() {
  int ret;
  ret = myVR.recognize(buf, 50);
  if(ret>0) {
    switch(buf[1]) {
      case onRecord:
        /** turn on LED */
        digitalWrite(led, HIGH);
        break;
      case offRecord:
        /** turn off LED*/
        digitalWrite(led, LOW);
        break;
      default:
        Serial.println("Record function undefined");
        break;
    }
    /** voice recognized */
    printVR(buf);
  }
}

The code is running fine. Now to start/stop display on OLED I have included all the necessary OLEd libraries and all and changed the above code only in the switch case as:

void loop() {
  int ret;
  ret = myVR.recognize(buf, 50);
  if(ret>0) {
    switch(buf[1]) {
      case OnRecord:
        display.clearDisplay();
        sensorValue = analogRead(sensorPin);
        display.setCursor(30,0);
        display.setTextSize(1);
        display.print("LDR Reading:");
        display.setCursor(30,10);
        display.setTextSize(2);
        display.print(sensorValue);
        delay(500);
        break;
      case OffRecord:
        display.clearDisplay();
        break;
      default:
        Serial.println("Record function undefined");
        break;
    }
    display.display();
    printVR(buf);
  }
}

Here when I say "on" the OLEd is starting on my voice command. But it remains frozen in the first reading. When I say "off" it turns of the display(as required). The process runs in loop.

I just want to keep on displaying LDR values by running all the statements in "case Onrecord" until case "offrecord" is encountered. Any idea how to do this?

The entire code for the voice controlled LDR readings on OLED is:

#include <SoftwareSerial.h>
#include "VoiceRecognitionV3.h"
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
int sensorPin = A0; // select the input pin for ldr
int sensorValue = 0;

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

 char inChar;
 String string;
/**        
  Connection
  Arduino    VoiceRecognitionModule
   2   ------->     TX
   3   ------->     RX
*/
VR myVR(2,3);    // 2:RX 3:TX, you can choose your favourite pins.
uint8_t records[7]; // save record
uint8_t buf[64];

#define OnRecord    (0)
#define OffRecord   (1) 

/**
  @brief   Print signature, if the character is invisible, 
           print hexable value instead.
  @param   buf     --> command length
           len     --> number of parameters
*/
void printSignature(uint8_t *buf, int len) {
  int i;
  for(i=0; i<len; i++) {
    if(buf[i]>0x19 && buf[i]<0x7F) {
      Serial.write(buf[i]);
    } else {
      Serial.print("[");
      Serial.print(buf[i], HEX);
      Serial.print("]");
    }
  }
}

/**
  @brief   Print signature, if the character is invisible, 
           print hexible value instead.
  @param   buf  -->  VR module return value when voice is recognized.
             buf[0]  -->  Group mode(FF: None Group, 0x8n: User, 0x0n:System
             buf[1]  -->  number of record which is recognized. 
             buf[2]  -->  Recognizer index(position) value of the recognized record.
             buf[3]  -->  Signature length
             buf[4]~buf[n] --> Signature
*/
void printVR(uint8_t *buf) {
  Serial.println("VR Index\tGroup\tRecordNum\tSignature");
  Serial.print(buf[2], DEC);
  Serial.print("\t\t");
  if(buf[0] == 0xFF) {
    Serial.print("NONE");
  } else if(buf[0]&0x80) {
    Serial.print("UG ");
    Serial.print(buf[0]&(~0x80), DEC);
  } else {
    Serial.print("SG ");
    Serial.print(buf[0], DEC);
  }
  Serial.print("\t");

  Serial.print(buf[1], DEC);
  Serial.print("\t\t");
  if(buf[3]>0) {
    printSignature(buf+4, buf[3]);
  }
  else{
    Serial.print("NONE");
  }
  Serial.println("\r\n");
}

void setup() {
  /** initialize */
  myVR.begin(9600);
  pinMode(13, OUTPUT);
  // initialize with the I2C addr 0x3C / mit I2C-Adresse 0x3c initialisieren
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.display();
  display.clearDisplay();
  display.setTextColor(INVERSE); 
  Serial.begin(115200);
  Serial.println("Elechouse Voice Recognition V3 Module\r\nControl LED sample");
  pinMode(sensorPin, INPUT);
  if(myVR.clear() == 0) {
    Serial.println("Recognizer cleared.");
  } else {
    Serial.println("Not find VoiceRecognitionModule.");
    Serial.println("Please check connection and restart Arduino.");
    while(1);
  }
  if(myVR.load((uint8_t)OnRecord) >= 0) {
    Serial.println("startRecord loaded");
  }
  if(myVR.load((uint8_t)OffRecord) >= 0) {
    Serial.println("endRecord loaded");
  }
}

void loop() {
  int ret;
  ret = myVR.recognize(buf, 50);
  if(ret>0) {
    switch(buf[1]) {
      case OnRecord:
        display.clearDisplay();
        sensorValue = analogRead(sensorPin);
        display.setCursor(30,0);
        display.setTextSize(1);
        display.print("LDR Reading:");
        display.setCursor(30,10);
        display.setTextSize(2);
        display.print(sensorValue);
        delay(500);
        break;
      case OffRecord:
        display.clearDisplay();
        break;
      default:
        Serial.println("Record function undefined");
        break;
    }
    display.display();
    printVR(buf);
  }
}

I am able to control the display of LDR readings on OLED using pushbutton. Initially it will be in "off" mode. Once I push the button it starts displaying LDr values in the interval of 500 milli seconds. Once I press the button again, It will clear the display.This will run in a loop.

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
int sensorPin = A0; // select the input pin for ldr
int sensorValue = 0;
bool toggle = false;
int buttonpin;


#define OLED_RESET 4 // not used / nicht genutzt bei diesem Display
Adafruit_SSD1306 display(OLED_RESET);

 char inChar;
 String string;


void setup()   { 

  pinMode(13, OUTPUT);

  buttonpin = 2; 
  pinMode(buttonpin, INPUT_PULLUP);
  // initialize with the I2C addr 0x3C / mit I2C-Adresse 0x3c initialisieren
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

  Serial.begin(9600);
  display.display();
  delay(2000);
  display.clearDisplay();

  display.setTextColor(INVERSE); 
}

void loop()
{
     if (digitalRead(buttonpin) == HIGH)
     {
      toggle = !toggle;
      while(digitalRead(buttonpin) == HIGH);
     }
      switch( toggle )
         {

          case 1:
           display.clearDisplay();
            sensorValue = analogRead(sensorPin);
            Serial.println(sensorValue); 
            display.setCursor(30,0); 
            display.setTextSize(1);
            display.print("LDR Reading:");
            display.setCursor(30,10); 
            display.setTextSize(2);
            display.print(sensorValue);
            delay(500);           

            break;

           case 0:
            display.clearDisplay(); 

            break;
           }
       display.display();



 }

If you could suggest how I should merge my previous code and the above code so that I could control the display using voice commands, It'll be great!!.

Thanks in advance!

4
  • Does the “freezed in first reading” thing, whatever it might be, happen to last about 500 milliseconds? What does “freezed in first reading” mean, exactly? ¶ Note, “changed the above code only in the switch case” probably is false. Not showing a Minimal, Complete, and Verifiable example of code – eg, you don't show declarations of display, sensorValue, and sensorPin, and don't indicate nature of sensor or model of OLED – makes it difficult to diagnose problems. Apr 15 '17 at 14:17
  • I mean to say that the OLED displays one LDR reading taken at the moment I say "on". And the display doesnt refresh to give continuous LDR reading . Eg : the OLED shows " LDR Reading :372" This will remain on the screen as it is until I say "off" which clears the display and make it blank. Then again when I say "on" , it displays another reading taken at the moment and it remains as it is on screen. I want the OLED to display continuous readings at an interval of 500 milli seconds and should clear the display once I say "off". I am uploading the full code. Apr 15 '17 at 15:08
  • For debugging, add a Serial.print() or and/or an OLED output (on a different line) that every half second or so tells the current sensor reading and the most-recent voice-unit output. Or temporarily add a button to simulate an On event. Do you know for sure that the sensor reading should change? Or does the OLED obviously blink each time a reading is put up? Do you know if an On event is occurring after the first On, or if it is a display issue? Apr 15 '17 at 16:33
  • I am just trying to print the analog values (example from basic arduino). Here I am getting analog values and I am trying to print the same on OLED. Without voice module , I am able to get the LDR readings on OLED. Now after adding the voice command, my statement is isnide switch case followed by break. I am able to verify whether my voice command is recorded or not from serial monitor. The problem is with code. The display should run in a loop showing LDR values after half second. The code is the problem. Apr 15 '17 at 17:32
1

But it remains frozen in the first reading.

because in the next run of loop(), the "ret = myVR.recognize(buf, 50);" returns a value of 0 -> no voice command is recognized.

the way to do it is to have a state machine like this:

  ret = myVR.recognize(buf, 50);  //read the voice command
  switch(buf[1]) {
      case OnRecord:
        if (vr_state == OffRecord) vr_state = OnRecord; //from previous off to on now
        break;
      case OffRecord:
        vr_state = OffRecord; //now to be off
        break;
      default:
        break; //do nothing -> keep status quo
  }
  //process vr_state
  switch (vr_state) ...

basically, there is potentially information even if no voice command is received (aka. previously OnRecord and now silence). your code's reaction to "ret" is dependent on its value now and its value previously.

0

To keep reading and reporting a sensor within loop() after each On command, until an Off command occurs, add a flag variable – eg, tellSensor – to control that reading and reporting. Declare the variable outside loop(), or declare it static within loop(), and initialize it false.

In the code for case OnRecord:, initialize the display (eg, clear display and print the LDR Reading: heading) and set tellSensor true.

In the code for case OffRecord:, clear the display and set tellSensor false.

After the end of the if(ret>0) { ... } if statement, say something like

if (tellSensor) {
   display.setCursor(30,10);
   display.setTextSize(2);
   display.print(sensorValue);
   delay(500);
}
2
  • I tried your solution. I initialized static bool Tellsensor= False in loop. Modified case OnRecord and OffRecord as you said. And after if(ret>0){..}.. added the if statement. But the results where same , the loop does not run when I say "On". It displays first reading and remains as it is. Once I say "off" it turns off the display. I tried moving the same if statement within if(ret>0){..} and here when I say "on" it displays one reading , again by saying "on" it refreshes and prints the next reading. By saying "off" the display goes blank. Any idea how to fix this? Apr 16 '17 at 7:34
  • By "static bool Tellsensor= False in loop", are you referring to a declaration and initialization right at the beginning of loop(), or some other loop? It should be the former. But the symptom sounds like it isn't. Anyway, for testing I'd move its declaration and initialization to global. Note, I'll be away a few days. Apr 16 '17 at 8:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.