Here is my code in which i want to make esp32 to advertise both as ibeacon and eddystone URL. In start it will act as a Ibeacon but when i write URL text from nrf connect app after connection URL beacon function is called and advertisement data changes to URL format from setBeacon() method.
#include "sys/time.h"
#include "BLEDevice.h"
#include "BLEUtils.h"
#include "BLEServer.h"
#include "BLEBeacon.h"
#include "esp_sleep.h"
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define GPIO_DEEP_SLEEP_DURATION 10 // sleep 4 seconds and then wake up
RTC_DATA_ATTR static time_t last; // remember last boot in RTC Memory
RTC_DATA_ATTR static uint32_t bootcount;
uint16_t beconUUID = 0xFEAA;
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
BLEAdvertising *pAdvertising;
struct timeval now;
const char turnIbeacon ='IBeacon';
const char turnURL ='URL';
BLEAdvertisementData oAdvertisementData = BLEAdvertisementData();
BLEAdvertisementData oScanResponseData = BLEAdvertisementData();
void setBeacon2() {
Serial.println("Function2 is called");
BLEBeacon oBeacon = BLEBeacon();
oBeacon.setManufacturerId(0x4C00); // fake Apple 0x004C LSB (ENDIAN_CHANGE_U16!)
oBeacon.setProximityUUID(BLEUUID(beconUUID));
oBeacon.setMajor((bootcount & 0xFFFF0000) >> 16);
oBeacon.setMinor(bootcount & 0xFFFF);
oAdvertisementData.setFlags(0x04); // BR_EDR_NOT_SUPPORTED 0x04
std::string strServiceData = "";
strServiceData += (char)26; // Len
strServiceData += (char)0xFF; // Type
strServiceData += oBeacon.getData();
oAdvertisementData.addData(strServiceData);
pAdvertising->setAdvertisementData(oAdvertisementData);
pAdvertising->setScanResponseData(oScanResponseData);
}
void setBeacon() {
char beacon_data[22];
Serial.println("Function is called");
beacon_data[0] = 0x10; // Eddystone Frame Type (Eddystone-URL)
beacon_data[1] = 0x20; // Beacons TX power at 0m
beacon_data[2] = 0x03; // URL Scheme 'https://'
beacon_data[3] = 'y'; // URL add 1
beacon_data[4] = 'o'; // URL add 2
beacon_data[5] = 'u'; // URL add 3
beacon_data[6] = 't'; // URL add 4
beacon_data[7] = 'u'; // URL add 5
beacon_data[8] = 'b'; // URL add 6
beacon_data[9] = 'e'; // URL add 7
beacon_data[10] = '.'; // URL add 8
beacon_data[11] = 'c'; // URL add 9
beacon_data[12] = 'o'; // URL add 10
beacon_data[13] = 'm'; // URL add 11
oAdvertisementData.setServiceData(BLEUUID(beconUUID), std::string(beacon_data, 14));
}
class MyCallbacks: public BLECharacteristicCallbacks
{
void onWrite(BLECharacteristic *pCharacteristic)
{
std::string value = pCharacteristic->getValue();
if (value.length() > 0)
{
Serial.println("*********");
Serial.print("New value: ");
for (int i = 0; i < value.length(); i++)
{
Serial.print(value[i]);
// if(value[i] == turnON)
// {
//setBeacon();
// }
//
/* If received Character is 0, then turn OFF the LED */
if(value[i] == turnIbeacon)
{
setBeacon();
}
}
Serial.println();
Serial.println("*********");
}
}
};
void setup()
{
Serial.begin(115200);
gettimeofday(&now, NULL);
Serial.printf("start ESP32 %d\n",bootcount++);
Serial.printf("deep sleep (%lds since last reset, %lds since last boot)\n",now.tv_sec,now.tv_sec-last);
last = now.tv_sec;
BLEDevice::init("ESP32-BLE-Server");
BLEServer *pServer = BLEDevice::createServer();
pAdvertising = BLEDevice::getAdvertising();
BLEDevice::startAdvertising();
setBeacon2();
BLEService *pService = pServer->createService(beconUUID);
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setCallbacks(new MyCallbacks());
pCharacteristic->setValue("Hello World");
pService->start();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
}
void loop()
{
delay(2000);
}
In initial run i was able to write something on esp32 using nrf connect app but now that write sign is not showing. And after connect when start i re-scan my device will disappears.
Note: Everything is running perfectly when i am uploading individual code of ibeacon and eddystone url on esp32
I am creating this temp monitoring system...Therefore, i want to get messages/alerts when the temperature are below 6 and again when they come back to above 6. Note: I don't want the alert (sendMailNormalValue():wink: to come when the system boots up....How do I deactivate the sendMailNormalValue(); and activate it only when the temp are below 6 (only to alert me when comes back to above 6)..
#include <OneWire.h>
#include <DallasTemperature.h>
// GPIO where the DS18B20 is connected to
const int oneWireBus = 5;
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(oneWireBus);
// Pass our oneWire reference to Dallas Temperature sensor
DallasTemperature sensors(&oneWire);
//========================================
float t;
int period = 30000;
unsigned long time_now = 0;
bool DisplayFirstTime = true;
int period1 = 30000;
unsigned long time_now1 = 0;
void sendMailBelowValue(){
}
void sendMailNormalValue(){
}
void setup() {
// put your setup code here, to run once:
Serial.begin (9600);
}
void loop() {
// put your main code here, to run repeatedly:
sensors.requestTemperatures();
t = sensors.getTempCByIndex(0);
float p=t-2;
// Check if any reads failed and exit early (to try again).
if (isnan(t)) {
Serial.println("Failed to read from sensor !");
delay(500);
return;
}
if (t>6){
if(millis() > time_now + period){
time_now = millis();
sendMailNormalValue();
Serial.print ("You got messagae");
}
}
if (t<6){
if(millis() > time_now1 + period1 || DisplayFirstTime){
DisplayFirstTime = false;
time_now = millis();
sendMailBelowValue();
}
}
}
I think I understand what you mean. On error (temp < 6), you want to send an email every 30 seconds; when the teperature reaches 6 or mode, send a single email to say the error condition has been fixed. On boot, only send an email if in error.
If that's it, you'll need to keep track of the error condition using a global flag.
// ...
bool tempError; // initialized in setup()
void setup()
{
// ...
float t;
for(;;) // loop until we get a valid reading.
{
t = sensors.getTempCByIndex(0);
if (!isnan(t))
break;
Serial.println("Failed to read from sensor !");
delay(500);
}
tempError = (t < 6);
}
void loop()
{
// read temp and check sensor...
// ...
if (t < 6)
{
tempError = true;
// send error email, set timer, etc...
}
else if (tempError)
{
// temp is now fine, after being too low.
tempError = false; // Clear error flag.
// send OK email, only once.
// Don't forget to clear the 30 second email timer !!!
}
}
Usually, you'd want some hysteresis in an alert system. You should consider waiting some seconds after the temperature has been 'fixed' before sending the 'OK' email. Otherwise you may end up getting lots of fail/fixed emails when the temperature is around 6 degrees. This is usually done with a simple state machine engine, but that is a bit beyond the scope of this questkon.
I have started a small project to hopefully replace RPis running a Java library with Arduinos.
(I am normally working with Java, so not as familiar with C)
There are multiple temp sensors connected to the board. I read the values and want to store them with a reference to the sensor address. When a value changes, an update of all the sensors with their address and the temperatures is send to the server (hence I need the store to compare the values every 10 seconds).
I am trying to use the HashMap from Arduino Playground, as on a first look it seemed to do what I need and seems lightweight.
However, when reading the address of the temp sensor from a variable from the HashMap it doesn't return the right one (when there is some data pre-set in the hashmap):
int strLen = sAddress.length();
char *cAddress = (char *)malloc(strLen+1);
sAddress.toCharArray(cAddress, strLen+1);
byte position = sensorHashMap.getIndexOf(cAddress);
However, if I replace the *cAddress with:
char *cAddress = "28aae25501412c";
it does find it. So what am I doing wrong?
My approach to store the temp values with the address as a reference might not be the best, and it seems that the code crashes later on when trying to update the value but I haven't gone down that far yet. If there is a better solution than I am very open to some suggestions off course.
The full code below:
#include <HashMap.h>
#include <OneWire.h>
#include <ESP8266WiFi.h>
#include <DS18B20.h>
char wifiSSID[] = "xxxx";
char wifiPassword[] = "xxxx";
unsigned long lastTempCheck = 0;
const byte HASH_SIZE = 10; // Max 10 (temp) sensors etc
HashType<char*, float> hashRawArray[HASH_SIZE];
HashMap<char*, float> sensorHashMap = HashMap<char*, float>( hashRawArray , HASH_SIZE );
int sensorsRegistered = 1;
WiFiClient client;
DS18B20 ds(5); // Is D1
void setup()
{
Serial.begin(115200);
Serial.println();
WiFi.begin(wifiSSID, wifiPassword);
Serial.print("Connecting");
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("---");
Serial.println("Connected to wifi");
Serial.print("Connected, IP address: ");
Serial.println(WiFi.localIP());
Serial.println("Setup completed, ready to run...");
// Test data
sensorHashMap[0]("name", 18);
sensorHashMap[1]("test", 200);
sensorHashMap[2]("qwer", 1234);
sensorHashMap[3]("28fffa6f51164ae", 123);
sensorHashMap[4]("28aae25501412c", 456);
}
void loop() {
// Duty cycle of the application
delay(100);
if ((millis() < lastTempCheck) || (millis() - lastTempCheck > 1000 * 10)) {
// Verifying the HashMap works with the pre-set values.
Serial.print("Checking pre-set values: ");
Serial.println( sensorHashMap.getIndexOf("28fffa6f51164ae"), DEC );
Serial.print("Checking sensor value: ");
Serial.println( sensorHashMap.getValueOf("28fffa6f51164ae") );
while (ds.selectNext()) {
float temp = ds.getTempC();
uint8_t address[8];
ds.getAddress(address);
String sAddress = "";
for (uint8_t i = 0; i < 8; i++) {
sAddress += String(address[i], HEX);
}
int strLen = sAddress.length();
char *cAddress = (char *)malloc(strLen+1);
sAddress.toCharArray(cAddress, strLen+1);
//char *cAddress = "28aae25501412c";
byte position = sensorHashMap.getIndexOf(cAddress);
Serial.print("Position: ");
Serial.println( position);
Serial.println( sensorHashMap.getIndexOf(cAddress), DEC );
if (position < HASH_SIZE) {
Serial.print("Updating sensor value, currently: ");
Serial.println( sensorHashMap.getValueOf(cAddress));
sensorHashMap[position](cAddress, temp); //ds.getTempC()
} else {
Serial.print("Creating sensor value, id is going to be ");
Serial.println(sensorsRegistered);
sensorHashMap[sensorsRegistered](cAddress, temp);
sensorsRegistered++;
}
free(address);
}
lastTempCheck = millis();
}
}
Currently i success to build the communication between the android device and arduino through bluetooth. As arduino will send string "ON" or "OFF" depend on the LED condition to Android through bluetooth and my android able to receive the string "LED:ARE:OFF" and "LED:ARE:ON" through the read() function. But currently i want to read a data by split the string into 3 from the LED, for example: "LED:ARE:OFF" into "LED" , "Are", "OFF" , but i failed to received the data. I had tried the String.split(":") to split out the aaa:bbb:ccc into 3 part, and it unable to read the data as well. Please help
Arduino Code:
#include <SoftwareSerial.h>// import the serial library
SoftwareSerial Genotronex(10, 11); // RX, TX
int ledpin=8; // led on D13 will show blink on / off
long previousMillis = 0; // will store last time LED was updated
long interval = 1000; // interval at which to blink (milliseconds)
int ledState = LOW; // ledState used to set the LED
long Counter=0; // counter will increase every 1 second
void setup() {
// put your setup code here, to run once:
Genotronex.begin(9600);
Genotronex.println("Bluetooth On please wait....");
pinMode(ledpin,OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
Counter+=1;
delay(4000);
// if the LED is off turn it on and vice-versa:
if (ledState == LOW){
ledState = HIGH;
Genotronex.print("LED:ARE:ON");
digitalWrite(ledpin, ledState);
}
else{
ledState = LOW;
Genotronex.print("LED:ARE:OFF");
digitalWrite(ledpin, ledState);
}
// set the LED with the ledState of the variable:
}
}
Android Code:
btnSend.setOnClickListener(this);
int delay = 1000; // delay in ms
int period = 100; // repeat in ms
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask()
{
public void run()
{
if (flag)
{
final byte data = read();
readMessageHandler.post(new Runnable()
{
public void run()
{
if (data != 1){
message = txtReceived.getText().toString() + (char)data;}
else{
message = "";
}
String message;
//New Code for split the data
String[] parts = message.split(":"); // escape .
String part0 = parts[0];
String part1 = parts[1];
String part2 = parts[2];
txtReceived.setText(part0);
//End of Split
// txtReceived.setText(Message);
}
});
}
}
}, delay, period);
private byte read()
{
byte dataRead = 0;
try
{
dataRead = (byte) inputStream.read();
}
catch(IOException readException)
{
toastText = "Failed to read from input stream: " + readException.getMessage();
Toast.makeText(Blood_Pressure.this, toastText, Toast.LENGTH_SHORT).show();
}
return dataRead;
}
I'm using an arduino uno with a CC3000 WiFi Shield. The ardunio counts people using a light barrier and then reports the countings to the xievly site. It seems to work fine for an hour or two but then nothing happens. Any ideas?
// Libraries
#include <Adafruit_CC3000.h>
#include <SPI.h>
#include <Time.h>
#include <TimeAlarms.h>
// Define CC3000 chip pins
#define ADAFRUIT_CC3000_IRQ 3
#define ADAFRUIT_CC3000_VBAT 5
#define ADAFRUIT_CC3000_CS 10
// Create CC3000 instances
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
SPI_CLOCK_DIV2); // you can change this clock speed
// WLAN parameters
#define WLAN_SSID "XX"
#define WLAN_PASS "XX"
#define WLAN_SECURITY WLAN_SEC_WPA2
// Xively parameters
#define WEBSITE "https://xively.com/feeds/XX"
#define API_key "XXX"
#define feedID "XXXX``"
uint32_t ip;
Adafruit_CC3000_Client client;
const unsigned long
connectTimeout = 15L * 1000L, // Max time to wait for server connection
responseTimeout = 15L * 1000L; // Max time to wait for data from server
// Visitor Counter
int anzahl =0;
int lastState=LOW;
const int inputPin = 2;
void setup()
{
// Initialize
attachInterrupt(0, count, RISING);
Serial.begin(115200);
if (!cc3000.begin())
{
while(1);
}
// Connect to WiFi network
cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY);
/* Wait for DHCP to complete */
while (!cc3000.checkDHCP())
{
delay(100);
}
unsigned long t = getTime();
cc3000.disconnect();
setTime(hour(t)+2,minute(t),second(t),month(t),day(t),year(t));
Alarm.alarmRepeat(9,59,59, Messung);
Alarm.alarmRepeat(10,59,59, Messung);
Alarm.alarmRepeat(11,59,59, Messung);
Alarm.alarmRepeat(12,59,59, Messung);
Alarm.alarmRepeat(13,59,59, Messung);
Alarm.alarmRepeat(14,59,59, Messung);
Alarm.alarmRepeat(15,59,59, Messung);
Alarm.alarmRepeat(16,59,59, Messung);
Alarm.alarmRepeat(17,59,59, Messung);
Alarm.alarmRepeat(18,59,59, Messung);
Alarm.alarmRepeat(19,59,59, Messung);
Alarm.alarmRepeat(22,59,59, Zeitkorrektur);
}
void count()
{
delay(10);
int val = digitalRead(inputPin);
if (val == HIGH && lastState==LOW)
{
anzahl++;
lastState=val;
}
else
{
lastState=val;
}
}
void Zeitkorrektur()
{
getTime();
}
void Messung()
{
datalog();
}
void loop()
{
Alarm.delay(1000);
}
// Minimalist time server query; adapted from Adafruit Gutenbird sketch,
// which in turn has roots in Arduino UdpNTPClient tutorial.
unsigned long getTime()
{
uint8_t buf[48];
unsigned long ip, startTime, t = 0L;
// Hostname to IP lookup; use NTP pool (rotates through servers)
if(cc3000.getHostByName("pool.ntp.org", &ip)) {
static const char PROGMEM
timeReqA[] = { 227, 0, 6, 236 },
timeReqB[] = { 49, 78, 49, 52 };
Serial.println(F("\r\nAttempting connection..."));
startTime = millis();
do {
client = cc3000.connectUDP(ip, 123);
} while((!client.connected()) &&
((millis() - startTime) < connectTimeout));
if(client.connected()) {
Serial.print(F("connected!\r\nIssuing request..."));
// Assemble and issue request packet
memset(buf, 0, sizeof(buf));
memcpy_P( buf , timeReqA, sizeof(timeReqA));
memcpy_P(&buf[12], timeReqB, sizeof(timeReqB));
client.write(buf, sizeof(buf));
Serial.print(F("\r\nAwaiting response..."));
memset(buf, 0, sizeof(buf));
startTime = millis();
while((!client.available()) &&
((millis() - startTime) < responseTimeout));
if(client.available()) {
client.read(buf, sizeof(buf));
t = (((unsigned long)buf[40] << 24) |
((unsigned long)buf[41] << 16) |
((unsigned long)buf[42] << 8) |
(unsigned long)buf[43]) - 2208988800UL;
Serial.print(F("OK\r\n"));
}
client.close();
}
}
if(!t) Serial.println(F("error"));
return t;
}
void datalog()
{
//noInterrupts();
// Connect to WiFi network
cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY);
/* Wait for DHCP to complete */
while (!cc3000.checkDHCP())
{
delay(100);
}
// Set the website IP
uint32_t ip = cc3000.IP2U32(216,52,233,120);
cc3000.printIPdotsRev(ip);
// Get data & transform to integers
int visitors = (int) anzahl/2; //Visitors going in and out therefore divided by 2
// Prepare JSON for Xively & get length
int length = 0;
String data = "";
data = data + "\n" + "{\"version\":\"1.0.0\",\"datastreams\" : [ {\"id\" : \"Visitors\",\"current_value\" : \"" + String(visitors) + "\"}]}";
length = data.length();
// Send request
Adafruit_CC3000_Client client = cc3000.connectTCP(ip, 80);
if (client.connected()) {
Serial.println("Connected!");
client.println("PUT /v2/feeds/" + String(feedID) + ".json HTTP/1.0");
client.println("Host: api.xively.com");
client.println("X-ApiKey: " + String(API_key));
client.println("Content-Length: " + String(length));
client.print("Connection: close");
client.println();
client.print(data);
client.println();
} else {
Serial.println(F("Connection failed"));
return;
}
Serial.println(F("-------------------------------------"));
while (client.connected()) {
while (client.available()) {
char c = client.read();
Serial.print(c);
}
}
client.close();
Serial.println(F("-------------------------------------"));
Serial.println(F("\n\nDisconnecting"));
cc3000.disconnect();
anzahl =0;
//interrupts();
}
In setup() you configured interrupt with RISING. That means that it fires when the pin goes from low state to high state. But in interrupt handler - count() you have strange logic which looks excessive since you already configured interrupt to fire only once on event.
Let's see what happens in count(). val will always be HIGH (well, considering only normal case, not glitches).. When the first interrupt comes lastState is LOW as initial value and we increment, but all successive calls will not because lastState is HIGH and never becomes LOW again.
So, to fix problem, we simply need to drop lastState because it's not needed
void count()
{
delay(10);
// avoiding glitches - check if it's still high
int val = digitalRead(inputPin);
if (val == HIGH)
anzahl++;
}