Android HCE with Arduino and Galaxy S3 cyanogenmod 11 - android

I' currently trying to get HCE running with my arduino uno device mounted with a seeed NFC Shield V 2.0
I'm using the example code from https://github.com/Seeed-Studio/PN532/blob/master/PN532/examples/android_hce/android_hce.ino
#include <SPI.h>
#include <PN532_SPI.h>
#include <PN532Interface.h>
#include <PN532.h>
PN532_SPI pn532spi(SPI, 10);
PN532 nfc(pn532spi);
void setup()
{
Serial.begin(115200);
Serial.println("-------Peer to Peer HCE--------");
nfc.begin();
uint32_t versiondata = nfc.getFirmwareVersion();
if (! versiondata) {
Serial.print("Didn't find PN53x board");
while (1); // halt
}
// Got ok data, print it out!
Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
// Set the max number of retry attempts to read from a card
// This prevents us from waiting forever for a card, which is
// the default behaviour of the PN532.
//nfc.setPassiveActivationRetries(0xFF);
// configure board to read RFID tags
nfc.SAMConfig();
}
void loop()
{
bool success;
uint8_t responseLength = 32;
Serial.println("Waiting for an ISO14443A card");
// set shield to inListPassiveTarget
success = nfc.inListPassiveTarget();
if(success) {
Serial.println("Found something!");
uint8_t selectApdu[] = { 0x00, /* CLA */
0xA4, /* INS */
0x04, /* P1 */
0x00, /* P2 */
0x07, /* Length of AID */
0xF0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* AID defined on Android App */
0x00 /* Le */ };
uint8_t response[32];
success = nfc.inDataExchange(selectApdu, sizeof(selectApdu), response, &responseLength);
if(success) {
Serial.print("responseLength: "); Serial.println(responseLength);
nfc.PrintHexChar(response, responseLength);
do {
uint8_t apdu[] = "Hello from Arduino";
uint8_t back[32];
uint8_t length = 32;
success = nfc.inDataExchange(apdu, sizeof(apdu), back, &length);
if(success) {
Serial.print("responseLength: "); Serial.println(length);
nfc.PrintHexChar(back, length);
}
else {
Serial.println("Broken connection?");
}
}
while(success);
}
else {
Serial.println("Failed sending SELECT AID");
}
}
else {
Serial.println("Didn't find anything!");
}
delay(1000);
}
void printResponse(uint8_t *response, uint8_t responseLength) {
String respBuffer;
for (int i = 0; i < responseLength; i++) {
if (response[i] < 0x10)
respBuffer = respBuffer + "0"; //Adds leading zeros if hex value is smaller than 0x10
respBuffer = respBuffer + String(response[i], HEX) + " ";
}
Serial.print("response: "); Serial.println(respBuffer);
}
void setupNFC() {
nfc.begin();
uint32_t versiondata = nfc.getFirmwareVersion();
if (! versiondata) {
Serial.print("Didn't find PN53x board");
while (1); // halt
}
// Got ok data, print it out!
Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
// configure board to read RFID tags
nfc.SAMConfig();
}
My android code is taken from the HCE development guide and I also tried the code form https://github.com/grundid/host-card-emulation-sample
My problem is, that the arduino code doesn't even recognize a tag. So all I'm getting is:
Waiting for an ISO14443A card
Didn't find anything!
Waiting for an ISO14443A card
Didn't find anything!
Waiting for an ISO14443A card
As a matter of fact, on the Android side, I do not receive any packet, neither is the fancy NFC sound playing, which usually indicates that at least something is happening.
So my question is, has someone tried to use the Galaxy S3 with cyanogenmod 10 along with HCE support. I'm really out of any ideas, I triplechecked my code, read a lots of question here on SO, but all did at least receive something from the NFC Shield.
I know that the common NFC mode works fine, as I have an application using NFC in "normal" mode. When I run this NFC-protocol on my arduino, all applications receive a packet, (although they can't route them correctly, because they are not adpu packets)

Android 4.4 HCE does not run on Samsung Galaxy S3 with NXP chip.
I had tested for both Galaxy Nexus, Nexus 7(2012) and Galaxy S3. All these 3 devices are not able to run HCE on Kitkat.
You may check the device for HCE support:
boolean isHceSupported =
getPackageManager().hasSystemFeature("android.hardware.nfc.hce");

Android HCE (as provided by the Android 4.4 HCE API) is not supported on CyanogenMod 10.*. That API is only available starting with CyanogenMod 11 and even then I'm not sure that the CyanogenMod implementation of the Android HCE API works on devices with NXP chipset (e.g. Galaxy S3).
CyanogenMod 10.* has a different HCE API. See Nikolay's blog for an example on how to use that API.
Basically, for your Arduino program to work, you would have to implement HCE based on the IsoPcdA technology.
Also note that if you ever switch from CyanogenMod HCE to Android HCE, you have to use ISO 7816-4 compliant APDUs. Thus, an "APDU" like you use it in your code above,
apdu[] = "Hello from Arduino";
would not work. CyanogenMod HCE, however, does not require the use of ISO 7816-4 APDUs on top of the ISO 14443-4 transport protocol and will, therefore, happily accept this string instead of an APDU.

Related

Reading NFC UID from android phone with PN532 and ArduinoMega

I am trying to use the PN532 to read my NFC UID from phone(Samsung Galaxy S10), but i receive just 08 and another 3 digits of random values.I read that a value that start with 08 is a RID(Random ID). Is there any possible way to read just a unique value, or use the PN532 to read something that is unique from my phones NFC?
I want to use that value to compare it with a constant in my code and send an impulse to a relay to open a door.
This code is from da Adafruit_PN532 library.
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_PN532.h>
#define PN532_IRQ (2)
#define PN532_RESET (3) // Not connected by default on the NFC Shield
// Or use this line for a breakout or shield with an I2C connection:
Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET);
void setup(void) {
Serial.begin(115200);
Serial.println("Hello!");
nfc.begin();
uint32_t versiondata = nfc.getFirmwareVersion();
if (! versiondata) {
Serial.print("Didn't find PN53x board");
while (1); // halt
}
Serial.print("Found chip PN5"); Serial.println((versiondata >> 24) & 0xFF, HEX);
Serial.print("Firmware ver. "); Serial.print((versiondata >> 16) & 0xFF, DEC);
Serial.print('.'); Serial.println((versiondata >> 8) & 0xFF, DEC);
// configure board to read RFID tags
nfc.SAMConfig();
Serial.println("Waiting for an ISO14443A Card ...");
}
void loop(void) {
uint8_t success;
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
// Wait for an ISO14443A type cards (Mifare, etc.). When one is found
// 'uid' will be populated with the UID, and uidLength will indicate
// if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
if (success) {
// Display some basic information about the card
Serial.println("Found an ISO14443A card");
Serial.print(" UID Length: "); Serial.print(uidLength, DEC); Serial.println(" bytes");
Serial.print(" UID Value: ");
nfc.PrintHex(uid, uidLength);
if (uidLength == 4) {
// We probably have a Mifare Classic card ...
uint32_t cardid = uid[0];
cardid <<= 8;
cardid |= uid[1];
cardid <<= 8;
cardid |= uid[2];
cardid <<= 8;
cardid |= uid[3];
Serial.print("Seems to be a Mifare Classic card #");
Serial.println(cardid);
}
delay(2000);
}
}
Do not use the NFC UID for any security purpose, as you can see a phone does give a random one for privacy purposes.
The NFC UID is designed only to help reading hardware deal with handling sending data to the right card when multiple different Tags are in range. There is no guarantee that the UID is actually Unique and that it cannot duplicated (even with Tag that are supposed to have it programmed at the factory you can buy clones from China where they can be programmed by the end user).
It is better to use cryptographic methods with data stored on a tag or emulated Tag if using a phone to provide uniqueness to use a Tag for anything with security implications.

Broadcast not triggered when using bluetoothLEScanner().startScan

Im trying to wake my application when the device enters a region of beacons with a specific UUID.
So far I tried using the native
BluetoothAdapter.getBluetoothLeScanner, providing a PendingIntent to launch a Broadcast reciever.
I also tried RxBleClient which is an amazing library which does work when doing a regular discovery.
I tried AltBeacon lib which is also a very thorough and brilliant lib.
I also tried play services Nearby Apis.
But all failed. They can all scan for beacons regularly but when trying to basically, register and let the device scan while in the bg. The broadcast never gets triggered.
I also tried all 4 while using a foreground service. That did not help either.
Ill also mention this is all done on Android 8.
I went over the code in both libs and they both eventually use the same function call from the native bluetoothadapter. So Im assuming if that fails, everything else will fail too.
Ill also mention that when supplying the startScan function with a CallBack instead of a PendingIntent, the callback is constantly triggered for all scanned BT devices. If I add a ScanFilter to filter for my UUID only, it fails.
What am I missing?
Btw, when I implemented this in Ios, it worked flawlessly. The app is awoken as if I used a Geofence enter/exit trigger.
Why wont this work in Android??
Any thoughts?
EDIT:
This is how I used the code from the AltBeacon library. It is basically a copy paste from the DOCS tutorial. Only difference is I encapsulated it in a seperate class:
public void init(AppCompatActivity context) {
if (isRegistered) {
return;
}
BluetoothManager bluetoothManager = (BluetoothManager) context.getApplicationContext().getSystemService(Context.BLUETOOTH_SERVICE);
if (bluetoothManager != null) {
bluetoothAdapter = bluetoothManager.getAdapter();
if (!bluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
context.startActivityForResult(enableBtIntent, 1002);
} else {
register(context);
}
}
}
public void register(AppCompatActivity context) {
if (isRegistered) {
return;
}
executorService.execute(new Runnable() {
#Override
public void run() {
Region region = new Region("com.sample.WakeOnDiscovery", Identifier.parse("E2C56DB5-DFFB-48D2-B060-D0F5A71096E0"), Identifier.fromInt(11180), null);
bootstrapRegion = new RegionBootstrap(new BootstrapNotifier() {
#Override
public Context getApplicationContext() {
return Application.getContextFromApplicationClass();
}
#Override
public void didEnterRegion(Region region) {
Logger.log(TAG, "didEnterRegion: " + region.toString());
}
#Override
public void didExitRegion(Region region) {
Logger.log(TAG, "didExitRegion: " + region.toString());
}
#Override
public void didDetermineStateForRegion(int i, Region region) {
Logger.log(TAG, "didDetermineStateForRegion: " + region.toString() + "|" + i);
}
}, region);
}
});
isRegistered = true;
}
This is when I try to scan for this specific UUID and major int (and without the major int). Only the didDetermineStateForRegion is triggered once I think. With int i = 0 or 1.
Regarding the UUID I tried 2 different UUIDs. The first is one that I generate in a sample app I wrote in IOS. The ios app advertises itself as a beacon. I can see it in a different app that uses a regular discovery function.
But the onEnterRegion does not trigger.
I also tried a UUID from an iBeacon device that I use regularly for years now.
Still no dice.
When I try using the native android ble scanner I use this:
ScanSettings settings = (new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)).setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES).build();
List<ScanFilter> filters = new ArrayList<>(); // Make a scan filter matching the beacons I care about
filters.add(new ScanFilter.Builder()/*.setServiceUuid(ParcelUuid.fromString("E2C56DB5-DFFB-48D2-B060-D0F5A71096E0"))*/.build());
bluetoothAdapter.getBluetoothLeScanner().startScan(filters, settings, getPendingIntent(context));
and:
private PendingIntent getPendingIntent(Context context) {
return PendingIntent.getBroadcast(context, 0, new Intent(context, BTDiscoveryBroadcast.class), PendingIntent.FLAG_UPDATE_CURRENT);
}
I tried passing null as filters, I tried an empty array list and I tried an actual filter with the same UUID.
Still nothing works.
what I did see by chance in logcat is this error message:
E/NearbyDirect: Could not start scan. [CONTEXT service_id=49 ]
java.lang.IllegalStateException: Receiver com.google.location.nearby.direct.bluetooth.state.FastPairScanner$4#535d6ea registered with differing handler (was Handler (adxv) {8fab16a} now Handler (android.app.ActivityThread$H) {e4e0078})
I think this occurs when using the AltBeacon lib as well. I can only assume this is related to my problem.
EDIT 2:
I tried this:
ScanSettings settings = (new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)).setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES).build();
List<ScanFilter> filters = new ArrayList<>(); // Make a scan filter matching the beacons I care about
byte[] manufacturerData = new byte[] {
// iBeacon identifier prefix
0x02, 0x15,
// Your Proximity UUID
(byte) 0xE2, (byte) 0xC5, 0x6D, (byte) 0xB5, (byte) 0xDF, (byte) 0xFB, 0x48, (byte) 0xD2, (byte) 0xB0, 0x60, (byte) 0xD0, (byte) 0xF5, (byte) 0xA7, 0x10, (byte) 0x96, (byte) 0xE0,
0x3, 0x20, 0x3, 0x20, (byte) 0xC5
};
int manufacturerId = 0x004c; // Apple
filters.add(new ScanFilter.Builder().setManufacturerData(manufacturerId, manufacturerData).build());
bluetoothAdapter.getBluetoothLeScanner().startScan(filters, settings, getPendingIntent(context));
The bytes data I retrieved after doing a regular .startDiscovery scan, locating my bt device and extracting from ScanResult the data. Just to make sure its precisely the same.
Still does not trigger broadcast :(
If you want to set up a scan filter to look for a beacon UUID, code like this won't work:
filters.add(new ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString("E2C56DB5-DFFB-48D2-B060-D0F5A71096E0")).build());
The above code will set a filter to look for a BLE device advertising a GATT Service UUID matching E2C56DB5-DFFB-48D2-B060-D0F5A71096E0. A GATT Service UUID has absolutely nothing to do with a Bluetooth Beacon Proximity UUID, even though both UUIDs may look superficially the same. In other words, you are telling the filter to look for a connectable bluetooth device that advertises a custom service that just happens to be the same as your beacon identifier. This will never find anything, because such a device is almost guaranteed not to exist.
What you want to do instead is more complicated -- you want to set up a scan filter that looks for a bluetooth LE manufacturer advertisement (which iBeacon and AltBeacon advertisements are), that have a specific manufacturer code and start with a certain sequence of bytes.
Getting the exact byte sequence for the filter is tricky because it depends on both the manufacturer ID the beacon layout (iBeacon or AltBeacon). This is one of the many complexities the Android Beacon Library handles for you.
If you really need to do it yourself you would do something like this for iBeacon (WARNING: untested code):
byte[] manufacturerData = new byte[] {
// iBeacon identifier prefix
0x02, 0x15,
// Your Proximity UUID
0xE2, 0xC5, 0x6D, 0xB5, 0xDF, 0xFB, 0x48, 0xD2, 0xB0, 0x60, 0xD0, 0xF5, 0xA7, 0x10, 0x96, 0xE0
};
int manufacturerId = 0x004c; // Apple
ScanFilter filter =
filters.add(new ScanFilter.Buider().setManufacturerData(manufacturerId, manufacturerData).build());

How can I use Arduino NFC to receive a key from Android and respond if valid?

I try to create an Android app that sends a key to an Arduino NFC Shield. I am able to send the key from the mobile and turn on the LED on the Arduino. But I don't know how to make the NFC shield send back to the Android device a response: valid key or not.
I get the message on Arduino, I am able to turn on the LED when the key is correct. The problem is that I need the NFC Shield to send back a message to the mobile phone, so that the app knows everything worked as expected or not.
I use NFC Shield PN532 (with Adafruit_PN532) in SPI mode.
success = nfc.inListPassiveTarget();
if(success) {
Serial.println("Found something!");
uint8_t selectApdu[] = {
0x00, /* CLA */
0xA4, /* INS */
0x04, /* P1 */
0x00, /* P2 */
0x05, /* Length of AID */
0xF2, 0x22, 0x22, 0x22, 0x22};
uint8_t response[255];
uint8_t responseLength = sizeof(response);
success = nfc.inDataExchange(selectApdu,
sizeof(selectApdu), response, &responseLength);
if(success) {
if(validKey(response, responseLength)){
Serial.println("Acces GRANTED.");
accesGranted();
}else{
Serial.println("Acces DENIED!!!!!!!!!!!!!!!!\n");
}
}
else{
Serial.println("Failed sending SELECT AID");
}
}

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.

Arduino: using Serial and Software Serial with bluetooth module

My purpose is to use Arduino to set up communication between a PC and an Android device using an HC-05 bluetooth module.
I use the USB communication between the PC and the Arduino (Serial Monitor) and a SoftwareSerial to connect to the HC-05.
My problem is that the communication works well from BT to the PC, but doesn't work as expected in the other way. When sending from the PC to BT all the characters sent are received by the BT device only when I close the Serial Monitor on the PC or when I reset the Arduino.
I've excluded a problem with the BT Module or the Android application because if in Arduino I implement an "ECHO" code (write in Android and the send in Android) everything works fine.
With the Arduino code posted below the expected behaviour is: Arduino reset-> Hello word sent, Serial monitor opened-> nothing happens, character written on serial monitor-> character received on BT, character written on BT-> character received on Serial Monitor, Serial monitor closed-> nothing happens.
The real behaviour is: Arduino reset-> Hello word sent, Serial monitor opened-> 2 Hello word on BT and 1 ("goodnight") on PC, character written on serial monitor-> nothing, character written on BT-> character received on Serial Monitor, Serial monitor closed-> previous written character(s) in serial monitor received + Hello Word.
How can I fix this problem?
Code:
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); // RX, TX
int a=0;
char c;
char d;
void setup() {
Serial.begin(9600);
Serial.println("Goodnight moon!");
mySerial.begin(9600);
mySerial.println("Hello, world?");
}
void loop() {
delay(10);
if (Serial.available()) {
c=Serial.read();
delay(10);
Serial.write(c);
}
delay(10);
if (mySerial.available()) {
d=mySerial.read();
delay(10);
mySerial.write(d);
}
}
This code is working for me on an Arduino Mini Pro (should be the same as UNO) with an HC-05. I have the HC-05 paired with my laptop. Using HyperTerminal on the COM port associated with the HC-05 and the Arduino serial console, I can send messages bidirectionally. The Serial.println statements show up in the Hyperterminal window like they should.
#include <SoftwareSerial.h>
#define rxPin 8
#define txPin 7
SoftwareSerial mySerial(rxPin, txPin); // RX, TX
char myChar ;
void setup() {
Serial.begin(9600);
Serial.println("Goodnight moon!");
mySerial.begin(9600);
mySerial.println("Hello, world?");
}
void loop(){
while(mySerial.available()){
myChar = mySerial.read();
Serial.print(myChar);
}
while(Serial.available()){
myChar = Serial.read();
mySerial.print(myChar);
}
}
I have implemented a serial communication between Arduino Uno and PC and this was my code, hope it can help:
int data;
char character;
int start_flag = 0;
void setup() {
Serial.begin(921600);
pinMode(2, OUTPUT);
}
void loop() {
if(Serial.available() > 0){
character = (char) Serial.read();
if(character == 's') {
start_flag = 1;
}
if(character == 't') {
start_flag = 0;
}
}
if (start_flag == 1) {
Serial.print(data); //data that was acquired by internal ADC
}
}
You could try this. It's about the simplest code you can use when testing Arduino bluetooth <-> C# communication. Note: the code was tested by connecting PIN1(TX) <-> MODULE RX, PIN2(RX) <-> MODULE TX and dividing the PIN1(TX) 5V to 2,5V before feeding it to the module.
Hope this helps all that are trying this!
Use this serial setup. With this code I can receive and send date to bluetooth from Serial Monitor
void setup(){
Serial.begin(9600); // Begin the serial monitor at 9600bps
bluetooth.begin(115200); // The Bluetooth Mate defaults to 115200bps
bluetooth.print("$"); // Print three times individually
bluetooth.print("$");
bluetooth.print("$"); // Enter command mode
delay(100); // Short delay, wait for the Mate to send back CMD
bluetooth.println("U,9600,N"); // Temporarily Change the baudrate to 9600, no parity
// 115200 can be too fast at times for NewSoftSerial to relay the data reliably
bluetooth.begin(9600); // Start bluetooth serial at 9600
pinMode(led, OUTPUT);
pinMode(buttonPin1, INPUT);
pinMode(buttonPin2, INPUT);
}
For more information, visit
http://www.circuitmagic.com/arduino/arduino-and-bluetooth-hc-06-to-control-the-led-with-android-device/
I recommend to use this app for testing:
https://play.google.com/store/apps/details?id=com.vagoscorp.virtualterminal
It let you see and send bytes as bytes(number from 0b00000000 to 0b11111111 (0 to 255 in decimal))
so you can make a simple echo firmware to test if your baudrate is correct and with that working, begin sending commands to turn on/off some LEDs
this is an echo code example:
char dato = 0;
void setup() {
Serial.begin(9600);//9600 is the default baudrate of the HC-05 (you can change it by AT commands, google it if you want)
//pinMode(13, OUTPUT); //enable this pin if you want to use de LED idea
//digitalWrite(13, HIGH);
}
//////////////////////////////////////////////////////////////////////////
void serialEvent() { //if you have received serial data
while (Serial.available() > 0) {
char dato = (byte)Serial.read();//save the byte
Serial.write(dato);//send the just received byte (echo)
}
}
///////////////////////////////////////////////////////////////////////////
void loop() {
}
I hope it helps you
Had the same problem, you have to view the BT module as 2 different baud rates on the wired side and the radio side. The radio side is set by whatever you connect at through putty, the wired side is programmed via AT commands. HC-05 defaults at 38400.

Categories

Resources