i'm working for a project using arduino and android studio, I would like to control my arduino from my mobile application by sending 0 t of 1, then I would like to receive arduino data on my android application,it is an obstacle detector that sends warning when there is an obstacle, here is the code of the arduino, it works because I tested with an application that I downloaded from google play, now I do not know how to display the message sent by arduino on my mobile application, and also how control the arduino from my app.
int echo = 3;
int trig = 2;
int greenled=4;
int redled=5;
float timelapse;
float distance;
char state=' ';
void setup() {
pinMode(greenled, OUTPUT);
pinMode(redled, OUTPUT);
pinMode(trig,OUTPUT);
pinMode(echo,INPUT);
digitalWrite(trig,LOW);
digitalWrite(greenled,LOW);
digitalWrite(redled,LOW);
Serial.begin(9600);
}
void loop() {
if (Serial.available()>0){
digitalWrite(trig,HIGH);
delayMicroseconds(10);
digitalWrite(trig,LOW);
timelapse=pulseIn(echo,HIGH);
distance = timelapse/58 ;
// if (distance > 200 || distance< 0 ) { Serial.println ( "Out of range"); }
if ( distance < 100 ) {
digitalWrite(redled, HIGH);
digitalWrite(greenled,LOW);
Serial.println("Attention");
delay(150);
}
else {
digitalWrite(redled,LOW);
digitalWrite(greenled,HIGH);
Serial.println("Libre");
}
delay(50);
}
else {
digitalWrite(redled,LOW);
digitalWrite(greenled,LOW);
digitalWrite(trig,LOW);
}
}
You didn't specify anything about how you're connecting your Arduino with your mobile phone. There are multiple ways to connect them together.
My wild guess here is that you're using a wired connection, as I see no code related to Bluetooth or any other communication.
If you're using OTG wired connection then, this would help.
Incase you want to do it wirelessly, you can read and write using serial port to a PC/Pi and then use a python script to upload the data to a cloud like firebase, and then read and data in your Android app from firebase. This is just one suggestion, there are many.
Related
I'm working on a cross-platform (iOS/Android) Xamarin app, in which I need to scan IBeacon devices to assert the distance between them and the phone device.
On iOS, I use the native iOS iBeacon API, which works flawlessly and as expected.
On Android, since Android does not natively support iBeacon, I use a mix of my own code and a library "UniversalBeacon". This approach works, but when it comes to scanning (or "ranging") for Beacons over a period of time, in order to constantly assess the distance of the phone device, the experince proves very unreliable.
I am experiencing that incoming BLE packets come in as expected, but only in intervals.
Roughly summarized: Packets will come in, in a steady stream, for a seemingly random amount of time, before the packets eventually stop coming in entirely. Then, after another seemingly random amount time, packets will start coming in again. This process repeats indefinitely.
So my question is: What is causing this issue? Is it an Android quirk that I somehow have to work around?
Initiating the scan:
_ScanCallback.OnAdvertisementPacketReceived += ScanCallback_OnAdvertisementPacketReceived;
var settings = new ScanSettings.Builder()
.SetScanMode(ScanMode.LowLatency)
.Build();
_Adapter.BluetoothLeScanner.StartScan(null, settings, _ScanCallback);
Callback implementation:
internal class BLEScanCallback : ScanCallback
{
public event EventHandler<BLEAdvertisementPacketArgs> OnAdvertisementPacketReceived;
public override void OnScanFailed([GeneratedEnum] ScanFailure errorCode)
{
base.OnScanFailed(errorCode);
}
public override void OnScanResult([GeneratedEnum] ScanCallbackType callbackType, ScanResult result)
{
base.OnScanResult(callbackType, result);
switch (result.Device.Type)
{
case BluetoothDeviceType.Le:
case BluetoothDeviceType.Unknown:
try
{
var p = new BLEAdvertisementPacket
{
BluetoothAddress = result.Device.Address.ToNumericAddress(),
RawSignalStrengthInDBm = (short)result.Rssi,
Timestamp = DateTimeOffset.FromUnixTimeMilliseconds(result.TimestampNanos / 1000000),
AdvertisementType = (BLEAdvertisementType)result.ScanRecord.AdvertiseFlags,
Advertisement = new BLEAdvertisement
{
LocalName = result.ScanRecord.DeviceName
}
};
if (result.ScanRecord.ServiceUuids != null)
{
foreach (var svc in result.ScanRecord.ServiceUuids)
{
var guid = new Guid(svc.Uuid.ToString());
var data = result.ScanRecord.GetServiceData(svc);
p.Advertisement.ServiceUuids.Add(guid);
}
}
var recordData = result.ScanRecord.GetBytes();
var rec = RecordParser.Parse(recordData);
foreach (var curRec in rec)
{
if (curRec is BLEManufacturerData md)
{
p.Advertisement.ManufacturerData.Add(md);
}
if (curRec is BLEAdvertisementDataSection sd)
{
p.Advertisement.DataSections.Add(sd);
}
}
OnAdvertisementPacketReceived?.Invoke(this, new BLEAdvertisementPacketArgs(p));
}
catch (Exception ex)
{
Debugger.Break();
}
break;
default:
break;
}
}
}
I've read in various articles that this could be caused by Android automatically suspending the scan in order to save power. Whether this is the case is not obvious to me, as there does not seem to be much support on the subject.
I've already tried the following:
Changing ScanMode to LowPower/Balanced - no change
Scanning with a filter set to the specific Beacon I was testing with - filter worked, but no change in regards to the issue
Implementing logic that restarts the scan in set intervals to work around potentional limits for scan duration imposed by Android - did not affect the issue
Using other, more broadly used libraries, such as Shiny.Beacons - same experience
The issue is not caused by the Beacon device itself not advertising correctly - I've made sure of this by scanning it on another device, at the same time as my app. It is the app itself that stops scanning and/or receiving its advertisement packets.
Thanks for your time :)
I encountered a strange problem when trying to unpair and pair again with my smartphone. Currently I write a C# application on UWP (Windows 10) for BLE connection with a remote device. I use my smartphone with nRF Connect App as the peripheral.
After being paired for a while (and being inactive), when unpairing and pairing again, the application gets stuck when trying to pair again.
I broke everything down to the most basal application I could create. This is a Console App that scans the existing devices and then unpairs and pairs with the selected device:
using BLE_Test;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static async Task Main(string[] args)
{
Dictionary<ulong, string> uuidDict = BleModule.Scan().Result;
Console.WriteLine("Devices found:");
int i = 0;
foreach (var uuid in uuidDict.Keys)
Console.WriteLine(string.Format("ID: {0}, UUID: {1}, Local Name: {2}", i++, uuid, uuidDict[uuid]));
Console.WriteLine("Select ID!");
int id = int.Parse(Console.ReadLine());
ulong selectedUuid = (uuidDict.ElementAt(id)).Key;
await BleModule.Unpair(selectedUuid);
await BleModule.Pair(selectedUuid);
Console.ReadLine();
}
}
}
It calls an UWP DLL called "BLE_Test" with the class "BleModule":
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.Advertisement;
using Windows.Devices.Enumeration;
namespace BLE_Test
{
public class BleModule
{
public static async Task<Dictionary<ulong, string>> Scan()
{
var uuidDict = new Dictionary<ulong, string>();
BluetoothLEAdvertisementWatcher watcher = new BluetoothLEAdvertisementWatcher();
watcher.Received += (BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs eventArgs)
=> AddAdvertisement(eventArgs, uuidDict);
watcher.Start();
await Task.Delay(10000);
watcher.Stop();
return uuidDict;
}
private static void AddAdvertisement(BluetoothLEAdvertisementReceivedEventArgs eventArgs, Dictionary<ulong, string> uuidDict)
{
if (uuidDict.ContainsKey(eventArgs.BluetoothAddress) == false)
uuidDict.Add(eventArgs.BluetoothAddress, eventArgs.Advertisement.LocalName);
}
public static async Task Pair(ulong uuid)
{
Console.WriteLine("Pairing...");
var bluetoothLEDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(uuid);
if (bluetoothLEDevice == null)
{
Console.WriteLine("UUID not found!");
return;
}
DeviceInformationCustomPairing customPairing = bluetoothLEDevice.DeviceInformation.Pairing.Custom;
customPairing.PairingRequested += (DeviceInformationCustomPairing sender, DevicePairingRequestedEventArgs args) => args.Accept(); // We auto-accept numeric comparison result for the sake of simplicity
DevicePairingResult result = await customPairing.PairAsync(DevicePairingKinds.ConfirmPinMatch);
Console.WriteLine("Pairing Result: " + result.Status.ToString());
}
public static async Task Unpair(ulong uuid)
{
Console.WriteLine("Unpairing...");
var bluetoothLEDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(uuid);
if (bluetoothLEDevice == null)
{
Console.WriteLine("UUID not found!");
return;
}
DeviceUnpairingResult result = await bluetoothLEDevice.DeviceInformation.Pairing.UnpairAsync();
Console.WriteLine("Unpairing Result: " + result.Status.ToString());
}
}
}
If I start the program for the first time, the pairing works fine (the unpairing will be ignored as the devices are not paired yet). If I start it immediately again afterwards, it also works fine. Unpairing and pairing will both take place. But if I wait a while (typically 5-10 minutes) while not doing anything, when I start the program again, it will unpair, but then it will wait indefinitely for PairAsync() to return. No coupling request will show on the nRF Connect App, and no PairingRequested event will appear.
Aborting the stuck program and restarting it won't help. In this case, even though the smartphone is found by the BluetoothLEAdvertisementWatcher, BluetoothLEDevice.FromBluetoothAddressAsync(uuid) will return null and the device can't be paired anymore. This can only be resolved by restarting the computer or switching off and on the advertisement in the nRF Connect App, as in this case a new random BLE Address is created for the device.
I have taken a snapshot of the BLE events using Btetlparse and Wireshark. It seems that there is a problem with a malformed package:
However, I don't really understand what is going wrong. Is this a problem of the nRF Connect App? Or the UWP commands? Or did I do something wrong? I tried two different smartphones (a Samsung Galaxy and an Oppo), so I doubt that it is a problem of the smartphone. I also added a DeviceWatcher, but this didn't change anything. Can anyone help me here?
I'm android developer and facing some autoConnect issue.
I'm using Arduino nano IOT and developed some simple application to communicate.
but I don't know why autoConnect doesn't work in this case.
Arduino nano continuously sends gyroscope sensing data(but only when app connected to module)
below is sample code.
#include <ArduinoBLE.h>
#include <Arduino_LSM6DS3.h>
BLEService sensorService("66df5109-edde-4f8a-a5e1-02e02a69cbd5");
BLEStringCharacteristic xSensorLevel("741c12b9-e13c-4992-8a5e-fce46dec0bff", BLERead | BLENotify,15);
BLEStringCharacteristic ySensorLevel("baad41b2-f12e-4322-9ba6-22cd9ce09832", BLERead | BLENotify,15);
BLEStringCharacteristic zSensorLevel("5748a25d-1834-4c68-a49b-81bf3aeb2e50", BLERead | BLENotify,15);
// last sensor data
float oldXLevel = 0;
float oldYLevel = 0;
float oldZLevel = 0;
long previousMillis = 0;
void setup() {
Serial.begin(9600);
while (!Serial);
if (!IMU.begin()) {
Serial.println("Failed to initialize IMU!");
while (1);
}
pinMode(LED_BUILTIN, OUTPUT);
if (!BLE.begin()) {
Serial.println("starting BLE failed!");
while (1);
}
BLE.setLocalName("Demo Gyroscope");
BLE.setAdvertisedService(sensorService);
sensorService.addCharacteristic(xSensorLevel);
sensorService.addCharacteristic(ySensorLevel);
sensorService.addCharacteristic(zSensorLevel);
BLE.addService(sensorService);
BLE.advertise();
Serial.println("Bluetooth device active, waiting for connections...");
}
void loop() {
BLEDevice central = BLE.central();
if (central) {
Serial.print("Connected to central: ");
Serial.println(central.address());
digitalWrite(LED_BUILTIN, HIGH);
while (central.connected()) {
//long currentMillis = millis();
updateGyroscopeLevel();
delay(300);
}
digitalWrite(LED_BUILTIN, LOW);
Serial.print("Disconnected from central: ");
Serial.println(central.address());
}
}
void updateGyroscopeLevel() {
float x, y, z;
if (IMU.gyroscopeAvailable()) {
IMU.readGyroscope(x, y, z);
if (x != oldXLevel) {
xSensorLevel.writeValue(String(x));
oldXLevel = x;
}
if (y != oldYLevel) {
ySensorLevel.writeValue(String(y));
oldYLevel = y;
}
if (z != oldZLevel) {
zSensorLevel.writeValue(String(z));
oldZLevel = z;
}
Serial.print(x);
Serial.print('\t');
Serial.print(y);
Serial.print('\t');
Serial.println(z);
}
}
and in my android app, I have set autoConnect true
private fun connectDevice(device: BluetoothDevice?) {
// update the status
broadcastUpdate(Actions.STATUS_MSG, "Connecting to ${device?.address}")
bleGatt = device?.connectGatt(context, true, gattClientCallback)
}
App can connect to module and read/write some data using UUID but when I turn off the module and turn on again, App cannot automatically connect it.
As far as I know, once I set it true, android store bt info as cache and trying to reconnect repeatedly.
(fyi, I'm not using Service to maintain connection)
but in my case, when I turn the module on again, it just shows below message in serial monitor
Bluetooth device active, waiting for connections...
It seems like app doesn't retry to connect.
I have read related questions and answers over here but couldn't find clue for my case.
My question over here is am I doing wrong? or this is normal behaviour?
when it comes to bt earphone, it's automatically connected when turn on. so I'm thinking something like that.
Please share any idea for this.
Really appreciate it!
After reading more articles, I found what's the issue.
Not sure if anyone reaching out to this question but in my case, I want app to reconnect to ble automatically even after turning off and on the ble.
But I found turning off/on the phone, turning off/on ble clear the cache in android internally. so Cannot automatically reconnect in this scenario.
Please have a look. this is really helpful for me
https://medium.com/#martijn.van.welie/making-android-ble-work-part-2-47a3cdaade07
This is not an answer but I found autoConnect is working when I use nRF Connect application. that means BT module itself has no issue and my application has issue.
I'm creating windows application in C++, which connect's PC with mobile via bluetooth and winsock. Allow's you to call and send messages from mobile via computer.
I'm using AT command's to tell mobile what i want to do. Pair with mobile device and force a call with At command
ATD+420******;
works perfect, but all commands for handling SMS like
AT+CMGL, AT+CMGF, AT+CMGS etc.
phone probably doesnt recognize them and returns ERROR.
Here is code which connects PC with mobile via bluetooth and socket:
SOCKADDR_BTH RemoteEndPoint;
RemoteEndPoint.port = 0;
RemoteEndPoint.addressFamily = AF_BTH;
RemoteEndPoint.btAddr = m_foundDevices[m_deviceIndex].Address.ullLong;
RemoteEndPoint.serviceClassId = HandsfreeServiceClass_UUID;
int BTHAddrLength = sizeof(RemoteEndPoint);
// Create the socket.
if ((m_localSocket = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM)) == INVALID_SOCKET)
{
// handle error.
}
// Connect the socket.
if ((iResult = connect(m_localSocket, (SOCKADDR *)&RemoteEndPoint, sizeof(RemoteEndPoint))) == INVALID_SOCKET)
{
// handle error.
}
Notice line
RemoteEndPoint.serviceClassId = HandsfreeServiceClass_UUID
I think the problem is here, becouse u cant send sms from Handsfree, but when i use another UUID, it doesnt even pair with mobile.
=== Here is just for info, how am i sending and receiving data from mobile ===
char recvbuf[DEFAULT_BUFLEN] = "";
const char *sendbuf = "AT+CMGL\r";
int len = (int)strlen(sendbuf);
if ((iResult = send(m_localSocket, sendbuf, len, MSG_OOB)) == SOCKET_ERROR)
{
// handle error. return ~0
}
if ((iResult = recv(m_localSocket, recvbuf, recvbuflen, 0)) == SOCKET_ERROR)
{
// handle error. return ~0
}
// Here recvbuf == "\r\nERROR\r\n"
-- I would like to find out the problem, why AT command's for SMS doesnt work.
Thank you for any advices!
If you have any question's about problem, i'll kindly explain.
Regards,
Filip.
EDIT
I found out answer "If you want to send SMS Messages, a Server Socket will be needed on the GSM Device", but after hours of googling i have no clue how to do that. Any suggestion's? Thank you.
I am beginning the basis for a home automation system using an arduino with ethernet and a phone with software that I programmed with MIT App inventor. I've been playing with code from a tutorial and got my LED to turn on and off fine from a local computer using the internet by using a browser and navigating the url 192.168.1.10/$1
/* thrown together by Randy Sarafan
Allows you to turn on and off an LED by entering different urls.
To turn it on:
http://192.168.1.10/$1
To turn it off:
http://192.168.1.10/$2
Based almost entirely upon Web Server by Tom Igoe and David Mellis
Edit history:
created 18 Dec 2009
by David A. Mellis
modified 4 Sep 2010
by Tom Igoe
*/
#include <SPI.h>
#include <Ethernet.h>
boolean incoming = 0;
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDA, 0x02 };
//IPAddress ip(191,168,1,15); //<<< ENTER YOUR IP ADDRESS HERE!!! i commented this out and did it on the router side
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
void setup()
{
pinMode(8, OUTPUT);
// start the Ethernet connection and the server:
Ethernet.begin(mac);
server.begin();
Serial.begin(9600);
}
void loop()
{
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
//reads URL string from $ to first blank space
if(incoming && c == ' '){
incoming = 0;
}
if(c == '$'){
incoming = 1;
}
//Checks for the URL string $1 or $2
if(incoming == 1){
Serial.println(c);
if(c == '1'){
Serial.println("ON");
digitalWrite(8, HIGH);
}
if(c == '2'){
Serial.println("OFF");
digitalWrite(8, LOW);
}
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
}
}
The problem I'm having is on the mobile side. I created an app with MIT app inventor that should toggle the IP, but instead gives me:
error 1109: The specified URL is not valid: 192.168.1.10/$1
Im quite perplexed. I know that this URL IS VALID because I've connected to it before. Is there a way to override this or otherwise fix it?
Here's the MIT app inventor AIA source: http://www.filedropper.com/internetled
You SHOULD specify the IP address in the code itself. And change "Ethernet.begin(mac);" to "Ethernet.begin(mac, ip);".
You should also try to open the web page in the browser to check if it works, before trying it out with App Inventor.
In AppInventor error "error 1109: The specified URL is not valid: 192.168.1.10/$1" you may have forgotten to put the "http: //" in your address.
Example, if you are saving the address in a global variable or tinyDB, you should put http://192.168.1.10/$1
This would be your address to connect the led.