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!
2 Answers 2
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.
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);
}
-
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?Vishruth Kumar– Vishruth Kumar04/16/2017 07:34:51Commented Apr 16, 2017 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.James Waldby - jwpat7– James Waldby - jwpat704/16/2017 08:19:18Commented Apr 16, 2017 at 8:19
display
,sensorValue
, andsensorPin
, and don't indicate nature of sensor or model of OLED – makes it difficult to diagnose problems.