Problems using and LDR to play Audio from SD card - android

I've hit a bit of a roadblock with my project. I've tried for hours and can't seem to find out what is causing my problem.
I'm trying to create a box that, when it's closed I can use bluetooth commands and arduino will play a response.
When you open the box, it will play a unique audio clip.
The problem is, the LDR works fine as in the unique clip plays whenever I open the box, however when the box is closed, the bluetooth responses don't play as expected, they just play a tiny snippet of the unique response from when it's open?
So once I open the box, the unique clip plays and the bluetooth responses work as expected.
I've tried using switch cases and for loops but to no avail.
Your help will be much appreciated!
//Coded By: Angelo Casimiro (4/27/14)
//Voice Activated Arduino (Bluetooth + Android)
//Feel free to modify it but remember to give credit
//PCM library used to turn voice file into a string of text for the speaker.
//Credit to HighTechLowTech
#include <SD.h> // need to include the SD library
//#define SD_ChipSelectPin 53 //example uses hardware SS pin 53 on Mega2560
#define SD_ChipSelectPin 4 //using digital pin 4 on arduino nano 328, can use other pins
#include <TMRpcm.h> // also need to include this library...
#include <SPI.h>
TMRpcm tmrpcm; // create an object for use in this sketch
int ldrPin = A2; //declared LDR on analog pin 2
int ldrValue = 0; //reading different values from the LDR
//declare voice as a string of data
String voice;
void setup() {
//Speaker pin
tmrpcm.speakerPin = 9;
Serial.begin(9600);
if (!SD.begin(SD_ChipSelectPin)) { // see if the card is present and can be initialized:
Serial.println("SD fail");
return; // don't do anything more if not
}
}
//-----------------------------------------------------------------------//
void loop() {
while (Serial.available()){ //Check if there is an available byte to read
delay(50); //Delay added to make thing stable
char c = Serial.read(); //Conduct a serial read
if (c == '#') {break;} //Exit the loop when the # is detected after the word
voice += c; //Shorthand for voice = voice + c
}
if (voice.length() > 0) {
Serial.println(voice);
}
//LDR variable defined from analog pin 2
ldrValue = analogRead(ldrPin);
//define LDR value ranges and map them to cases
//if voice string is "marco" then playback the sample array
if(voice == "*marco") {tmrpcm.play("Polo!.wav");}
else if(voice == "*hello") {tmrpcm.play("Hello!.wav");}
else if(voice == "*where") {tmrpcm.play("here.wav");}
else if(voice == "*who") {tmrpcm.play("Scott.wav");}
else if(voice == "*knock knock") {tmrpcm.play("Who.wav");}
else if(ldrValue > 500) {tmrpcm.play("Burp.wav");}
voice="";
delay(1);
}
It might be easier to see in this sketch using switch cases.
Basically, when the box is closed i can see in the serial monitor that case 2 is active which is what I want.
When the box is open, case 1 is active, but it's not playing 'Burp.wav' until I close it again and it switches back to case 2
//Coded By: Angelo Casimiro (4/27/14)
#include <SD.h> // need to include the SD library
//#define SD_ChipSelectPin 53 //example uses hardware SS pin 53 on Mega2560
#define SD_ChipSelectPin 4 //using digital pin 4 on arduino nano 328, can use other pins
#include <TMRpcm.h> // also need to include this library...
#include <SPI.h>
TMRpcm tmrpcm; // create an object for use in this sketch
//declare voice as a string of data
String voice;
//LDR value Range
const int sensorMin = 100;
const int sensorMax = 480;
void setup()
{
//Speaker pin
tmrpcm.speakerPin = 9;
Serial.begin(9600);
if (!SD.begin(SD_ChipSelectPin))
{
// see if the card is present and can be initialized:
Serial.println("SD fail");
return; // don't do anything more if not
}
}
//-----------------------------------------------------------------------//
void loop()
{
while (Serial.available())
{
//Check if there is an available byte to read
delay(50); //Delay added to make thing stable
char c = Serial.read(); //Conduct a serial read
if (c == '#')
{
break; //Exit the loop when the # is detected after the word
}
voice += c; //Shorthand for voice = voice + c
}
if (voice.length() > 0)
{
Serial.println(voice);
}
//LDR variable defined from analog pin 2
int sensorReading = analogRead(A2);
Serial.println(sensorReading);
//define LDR value ranges and map them to cases
int range = map(sensorReading, sensorMin, sensorMax, 1, 2);
Serial.println(range);
switch (range)
{
case 1:
{
tmrpcm.play("Burp.wav");
}
break;
case 2:
//if voice string is "marco" then playback the sample array
if (voice == "*marco")
{
tmrpcm.play("Polo!.wav");
}
else if (voice == "*hello")
{
tmrpcm.play("Hello!.wav");
}
else if (voice == "*where")
{
tmrpcm.play("here.wav");
}
else if (voice == "*who")
{
tmrpcm.play("Scott.wav");
}
else if (voice == "*knock knock")
{
tmrpcm.play("Who.wav");
}
voice = "";
break;
}
delay(50);
Serial.println();
}

Related

How to exit void loop in Arduino if there is no serial data available?

I am building an internet controlled robot that uses 2 android phones for controlling.
The first phone is connected to Arduino Uno via USB and serves as a 3G shield
The second phone is used to control the whole thing. It sends unassigned byte to the first phone which sends it to Arduino.
The apps I uses on the phones have one problem. The joystick in the app doesn't send a specific command when its in rest. For example when I move it up it sends "1" to the phone connected to the Arduino which drives the motors forward but when I release the joystick it stops sending data however the motors on my robot still spin until I move the joystick down which sends "2" motor.run(RELEASE);
How can I stop the motors if there is no Serial Data available?
This is the code i wrote.
#include <AFMotor.h>
AF_DCMotor motor_left(2, MOTOR12_1KHZ);
AF_DCMotor motor_right(3, MOTOR12_1KHZ);
int ledPin = 13;
int speed_min = 100; //the minimum "speed" the motors will turn - take it lower and motors don't turn
int speed_max = 1000; //the maximum "speed" the motors will turn – you can’t put in higher
int speed_left = speed_max; // set both motors to maximum speed
int speed_right = speed_max;
int command = 0;
void setup ()
{
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
motor_left.setSpeed(255);
motor_left.run(RELEASE);
motor_right.setSpeed(255);
motor_right.run(RELEASE);
motor_left.setSpeed(speed_left); // minimum speed 135 max speed 255
motor_right.setSpeed(speed_right); // minimum speed 135 max speed 255
}
void loop() {
if (Serial.available() > 0);
byte command = Serial.read();
if (command == 1)
{
Serial.println("Move Forward");
digitalWrite(ledPin, HIGH);
motor_left.run(FORWARD);
}
if (command == 2)
{
Serial.println("Stop");
digitalWrite(ledPin, LOW);
motor_left.run(RELEASE);
}
}
So basically it should do nothing if there is no data available.
Use your code like this, it will help
void loop() {
if (Serial.available() > 0) {
byte command = Serial.read();
if (command == 1) {
Serial.println("Move Forward");
digitalWrite(ledPin, HIGH);
motor_left.run(FORWARD);
} else if (command == 2) {
Serial.println("Stop");
digitalWrite(ledPin, LOW);
motor_left.run(RELEASE);
} else {
//put your code to stop Motor
}
}
}

use char as an operator?

I am making an android app + arduino that will receive ir code from arduino and sending the results.value (ir decode) to android through bluetooth. on the android side I have receive the code as a String that results into (for example) 92c0 then made a test button that will send it back to arduino and trigger it to send ir code to a device by irsend.sendNEC(0x92c0, 32) problem is when receiving the codes back from the android app is I have to receive it by char data, how do I use data which is a char and use it as a substitute for 0x92c0 in irsend.sendN My sketch down below:
#include <IRremote.h>
#include <SoftwareSerial.h>
SoftwareSerial bluetoothPort(4,5);
const int RECV_PIN = 12;
char data = "0";
const int SEND_PIN = 13;
IRsend irsend;
IRrecv irrecv(RECV_PIN);
decode_results results;
int BTval;
int IRval;
void setup()
{
bluetoothPort.begin(9600);
Serial.begin(9600);
irrecv.enableIRIn();
}
void loop()
{
if(bluetoothPort.available() > 0)
{
data = bluetoothPort.read();
Serial.print(data);
irsend.sendNEC(operator[data],32);
irrecv.resume();
}
if(irrecv.decode(&results))
{
Serial.println(results.value);
int set = results.value;
bluetoothPort.println(results.value, HEX);
irrecv.resume();
}
}
The problem here is that you CAN'T transfer 0x92c0 as a char (or byte). Just because it is not a byte, but two.
Now, I'm not much into android, so I need to see the android code to make a real solution You can handle this in three ways:
Binary transfer the data (2 bytes)
Transfer the data as a string (5 bytes)
Index the possible replies in an array and transfer the index (only applicable for a small quantity of codes).
I'm showing you the last 2, because the 1st is the most effective but I don't think you have the proper knowledge to send and receive data in binary format from android (and surely I don't have it).
So, if the data is transferred in string format (the same way you are uploading it) you will receive more bytes:
1 to 4 hexadecimal digits
1 carriage return
The code just stores the bytes you receive in a variable and then sends it when you receive a CR or LF:
// Outside the loop function
uint16_t receivedData;
// Inside the loop function
if(bluetoothPort.available() > 0)
{
data = bluetoothPort.read();
if ((data >= '0') && (data <= '9'))
{ // If it is a digit between 0 and 9 (in ascii)
receivedData = (receivedData << 4) | (data - '0');
}
else if ((data >= 'A') && (data <= 'F'))
{ // If it is a digit between A and F (in ascii)
receivedData = (receivedData << 4) | (data - 'A' + 10);
}
else if ((data >= 'a') && (data <= 'f'))
{ // Lowercase case
receivedData = (receivedData << 4) | (data - 'a' + 10);
}
else if (((data == '\r') || (data == '\n')) && (receivedData > 0))
{ // I tend to consider both CR and LF, because windows always screws this
Serial.print(receivedData, HEX);
irsend.sendNEC(receivedData,32); // Not sure about the 32 here...
irrecv.resume();
receivedData = 0;
}
else
receivedData = 0; // Something went wrong, just reset the variable
}
If you just have to send a few codes, you can store them and then transfer only the proper index. For instance:
// Outside the loop function
uint16_t possibleCodes[] = { 0x92c0, 0x8238, 0x5555 };
// Inside the loop function
if(bluetoothPort.available() > 0)
{
data = bluetoothPort.read();
// If you are using string transmission, use the following
// line to get the correct value
// data = bluetoothPort.read() - '0';
if (data < sizeof(possibleCodes) / sizeof(possibleCodes[0]))
{
Serial.print(possibleCodes[data], HEX);
irsend.sendNEC(possibleCodes[data],32); // Not sure about the 32 here...
irrecv.resume();
}
}
For instance in this case to send 0x92c0 you will have to send from android the value 0.

Weird behaviour after deleting/commenting code

I've run into some weird behaviour and looks like I can't find an answer. I've written some simple code to control a servo motor via bluetooth using my phone.
#include <Servo.h>
#include "SoftwareSerial.h";
int servoPin = 2;
int bluetoothTx = 11;
int bluetoothRx = 10;
SoftwareSerial bluetooth(bluetoothTx, bluetoothRx);
Servo myservo;
char unChar;
String readString;
void setup() {
Serial.begin(9600);
bluetooth.begin(115200);
delay(100);
bluetooth.begin(9600);
myservo.attach(servoPin, 800, 2200);
}
void loop() {
if (bluetooth.available()) {
unChar = bluetooth.read();
Serial.println(unChar);
if (unChar == 'A') {
motor();
}
}
}
void motor() {
delay(15);
while (bluetooth.available()) {
char c = bluetooth.read();
readString += c;
}
if (readString.length() > 0) {
Serial.println(readString.toInt());
myservo.write(readString.toInt());
readString = "";
}
}
For android, I used the MIT App Inventor to make a basic slider.
I'm using an Arduino Mega 2560, Power HD High-Torque High-Voltage Digital Servo 1218TH and a Bluetooth Mate Silver RN-41.
Everything works fine with the exception of the servo stuttering while dragging the slider on the phone. That is one small problem. The weird behaviour appears when I comment or delete my code in the arduino loop. The servo still stutters on its place when I play with the slider. What causes this behaviour?
Try to re-adjust the delay time after delete comment, it happens because add debug log inside the loop needs time to show up. In other words, that comment inside the loop has an impact on delay time.

Communicating with Nexus-4 using libusb in firmware update mode

I am trying to develop a simple program to communicate with the Nexus-4 bootloader in firmware update mode.
Nexus -4 has three usb interfaces. Interface-1 has two 2 endpoints - 2 and 131.
I wrote a program to write the command, get-device-info, through endpoint 2 and listen at endpoint 131 for the reply.
(I tried all permutations of interfaces and endpoints!).
The program successfully writes the command to the device but nothing is read from the device.
Command format: Flag(0x7e): CMD: Data (variable length): CRC-16: Flag(0x7e)
Get-device-info-command: 0x7e 0x00 0x78 0xf0 0x7e
The following is the program.
#include <stdio.h>
#include <stdlib.h>
#include <libusb-1.0/libusb.h>
#define INTERFACE 1
#define EP_OUT 2
#define EP_IN 131
int main() {
libusb_device **devs; // retrieve a list of devices
libusb_device_handle *dev_handle; // device handler
libusb_context *ctx = NULL; //a libusb session
int r, r2, i;
ssize_t cnt; //holding number of devices in list
unsigned char data[30],read_data[512]; //data to write
data[0]=0x7e;data[1]=0x00;data[2]=0x78;data[3]=0xf0;data[4]=0x7e; // get-device-info command in HLDC format
int actual,read_actual;
r = libusb_init(&ctx);
if(r < 0) {
printf("Init Error\n");
return 1;
}
libusb_set_debug(ctx, 3);
cnt = libusb_get_device_list(ctx, &devs); //get the list of devices
if(cnt < 0) {
printf("Get Device Error\n");
return 1;
}
printf("%d Devices in list\n",(int)cnt);
dev_handle = libusb_open_device_with_vid_pid(ctx, 4100, 25371); //these are vendorID and productID I found for Nexus-4 firmware update
if(dev_handle == NULL)
printf("Cannot open device\n");
else
printf("Device opened\n");
libusb_free_device_list(devs, 0); //free the device list
if(libusb_kernel_driver_active(dev_handle, INTERFACE) == 1) { //find out if kernel driver is attached
printf("Kernel Driver Active\n");
if(libusb_detach_kernel_driver(dev_handle, INTERFACE) == 0) //detach it
printf("Kernel Driver Detached!\n");
}
r = libusb_claim_interface(dev_handle, INTERFACE); //claim interface 1 Nexus-5/4 FUM
if(r < 0) {
printf("Cannot Claim Interface\n");
printf("%s\n",libusb_error_name(r));
return 1;
}
printf("Claimed Interface\n");
printf("Data to be send -> %s\n",data); //just to see the data that we are writing
printf("Writing Data...\n");
r = libusb_bulk_transfer(dev_handle, (EP_OUT | LIBUSB_ENDPOINT_OUT), data, 5, &actual, 0);
if(r == 0 && actual == 5){ //we wrote successfully 5 bytes to the device
printf("Writing Successful!\n");
printf("Waiting to read from device!\n");
r2 = libusb_bulk_transfer(dev_handle, (EP_IN | LIBUSB_ENDPOINT_IN), read_data, 512, &read_actual, 5000);
if (r2 >=0){
if (read_actual > 0){
printf("Data received by bulk transfer\n");
printf("Data is ");
for (i=0; i<read_actual; i++)
printf("%x ",read_data[i]);
printf("\n");
}
else{
printf(stderr, "No data received in bulk transfer (%d)\n", r2);
return -1;
}
}
else{
fprintf(stderr, "Error receiving data via bulk transfer %d\n", r2);
return r2;
}
}
else
printf("Write Error\n");
r = libusb_release_interface(dev_handle, INTERFACE); //release the claimed interface
if(r!=0) {
printf("Cannot Release Interface\n");
return 1;
}
printf("Released Interface\n");
libusb_close(dev_handle);
libusb_exit(ctx);
return 0;
}
The program is able to send the command successfully to the phone but it is not able to receive any response from the phone. When I run the program, I get the following output:
10 Devices in list
Device opened
Kernel Driver Active
Kernel Driver Detached!
Claimed Interface
Data to be send -> ~
Writing Data...
Writing Successful!
Waiting to read from device!
Error receiving data via bulk transfer -7
I am not sure the reason for not getting a response is because of the wrong command structure or because of the implementation of the program?

Arduino Mega ADK strange acc.write() behavior (huge delay) NAK issue seemd to be confirmed. Android generates NAK's as a result of acc.write

I'm trying to communicate between Arduino Mega Adk (ADK 2011) and android device.
Something goes ok, but something goes completely wrong.
Transfer data from Android to Arduino via acc.read from Arduino side works fine.
But when i try to send some bytes from Arduino to Android - something strange happens.
First of all here is Arduino sketch:
#include <Max3421e_constants.h>
#include <Max3421e.h>
#include <Usb.h>
#include <AndroidAccessory.h>
#define COMMAND_LED 0x2
#define TARGET_PIN_18 0x12
#define TARGET_PIN_19 0x13
#define V_ON 0x1
#define V_OFF 0x0
#define PIN_18 18
#define PIN_19 19
#define INPUT_PIN 30
AndroidAccessory acc("Google, Inc.",
"DemoKit",
"Ololo device board",
"1.0",
"http://www.android.com",
"0000000012345678");
byte rcvmsg[3];
byte sndmsg[3];
int buttonState = 0;
void setup();
void loop();
void led_setup(){
pinMode(PIN_18, OUTPUT);
pinMode(PIN_19, OUTPUT);
pinMode(INPUT_PIN, INPUT);
}
void setup()
{
Serial.begin(115200);
Serial.print("\r\nStart");
led_setup();
acc.powerOn();
}
void loop()
{
if (acc.isConnected()) {
buttonState = digitalRead(INPUT_PIN);
if (buttonState == 1){
sndmsg[0] = 0x2;
sndmsg[1] = 0x1;
sndmsg[2] = 0x1;
int len = acc.write(sndmsg, 3);
digitalWrite(PIN_19, HIGH);
}
else {
//Nothing here for test
}
}
//usefull test for button
buttonState = digitalRead(INPUT_PIN);
if (buttonState == 1){
digitalWrite(PIN_19, HIGH);
}
else {
digitalWrite(PIN_19, LOW);
}
}
Ok. When acc.write() is executed it takes up to ~1 second to transfer data to android. And this time doesn't depend on number of bytes in sndmsg. Only if i execute acc.write(sndmsg,0) (sending 0 bytes) - everything goes fast.
That is a little bit disturbing. I've tried to change board to another one but have got the same result.
Any advices? may be that is a common bug, but there is no such much information in web.
UPD:
Wrote some very simple code, that only sends 3 bytes via acc.write.
here it is:
#include <Max3421e_constants.h>
#include <Max3421e.h>
#include <Usb.h>
#include <AndroidAccessory.h>
AndroidAccessory acc("Google, Inc.",
"DemoKit",
"Demokit board",
"1.0",
"http://www.android.com",
"0000000012345678");
byte msg[3];
unsigned long time;
void setup();
void loop();
void led_setup(){
}
void setup()
{
Serial.begin(115200);
Serial.print("\r\nStart");
acc.powerOn();
}
void loop()
{
if (acc.isConnected()) {
Serial.print("\r\nis Connected");
msg[0] = 0x1;
msg[1] = 0x1;
msg[2] = 0x1;
//Serial.print("\r\nSending");
time = millis();
Serial.print ("\r\nBefore write\r\n");
Serial.print (time);
acc.write(msg, 3);
time = millis();
Serial.print("\r\nAfter write: \r\n");
Serial.print (time);
//delay(500);
}
}
And it's debug output is:
is Connected
Before write
6983
After write:
10958
is Connected
Before write
10958
After write:
14491
is Connected
and so on. So on some reasons acc.write takes a lot of time and there is no data in the android app.
New UPD (19.01.2015):
Today i've performed some experiments. Here are results.
First, i've looked into AndroidAccessory.cpp and found write function:
int AndroidAccessory::write(void *buff, int len)
{
usb.outTransfer(1, out, len, (char *)buff);
return len;
}
Ok, then i looked into usb host shield library and found there usb.cpp with outTransfer fucntion, that returns error code if ouccured and 0x00 if everything is ok.
So i modified write function to return an error code instead of lenght, like this:
int AndroidAccessory::write(void *buff, int len)
{
byte rcode;
rcode = usb.outTransfer(1, out, len, (char *)buff);
return int(rcode);
}
and recived "4" as result.
According to MAX3421Econstants.h it is hrNAK (0x04) error code.
Any ideas? Looks like accessory does not recive NAKs from Android and write fails as a result.
Situation update:
Did some research. There is a hell of NAK's when accessory is connected. Here is dump from usb connector:
i found the solution. And it is very simple - i didn't setup communication with accessory correctly.
This is not an Arduino problem. Arduino works fine.
It is just how android interacts with android accessory.
So, results:
When AndroidAccessory is plugged to Android and Android haven't setup
communication with the accessory yet, Android OS will send a lot of
USB NAKs to the accessory and this is normal.
You must be careful
during setuping communication with the accessory. If you make some
mistakes, you can receive same situation: Probably possible to write
to the accessory, but accessory isn't possible to write to the
android.
If UsbManager opens accessory correctly, it stops sending
NAKs and starts recieve data from arduino.
It is a little bit strange for me, because it was really hard to found a problem: i have an application, written according to this manual: http://developer.android.com/guide/topics/connectivity/usb/accessory.html But, because i'm not very familiar with android, it seems that i've done some mistakes and receive strange behavior:
i was able to write to arduino
i was able to retrive information about arduino as android accessory
it was possible to ask for permissions
but when arduino tries to write to android, it recievs a lot of NAKs
So i decided to rewrite program in more simple way, just with one function and tried to do it in right way. And after some debugging it finally started to work as i want.
So thank everyone, who spend time for reading this.
Bonus: dump of normal packet, ended with EOP not NAK
UPD 26.01.2015:
I found problem and it was in my android code.
here is explanation:
Android developer's manual said that function, which set up communication with accessory must start it's own thread in which all communications with input and output streams are held. Smth like this:
private void openAccessory() {
Log.d(TAG, "openAccessory: " + accessory);
mFileDescriptor = mUsbManager.openAccessory(mAccessory);
if (mFileDescriptor != null) {
FileDescriptor fd = mFileDescriptor.getFileDescriptor();
mInputStream = new FileInputStream(fd);
mOutputStream = new FileOutputStream(fd);
Thread thread = new Thread(null, this, "AccessoryThread");
thread.start();
}
}
I really messed this thing up. Forgot about creating new thread in openAccessory function and tried to do it in different place. And recieve a hell of NAK's. Then i've changed my code and add some debug-like run() function like this:
public void run() {
final byte[] buffer = new byte[16384];
int ret = 0;
int i = 0;
while (i<50) {
try {
ret = mInputStream.read(buffer);
i++;
Thread.sleep(500);
} catch (IOException e) {
break;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
And until this run method exists (while i < 50) android reads arduino correctly. And when thread ends up (i > 50) - Arduino starts to readout Error Code 4 (NAK) from Android.
That's all folks.

Categories

Resources