Use HM-10 to detect Estimot beacon distance - arduino

I would like to make my Arduino+HM-10 detect Estimote beacon distance without using phone connection but I’m not sure it’s even possible.
Can I detect the beacon only with HM-10?
Can I estimate the distance between my Arduino+HM-10 and the beacon? I know Apple didn’t publish the algorithm but I have already estimated distance to a beacon with a Cordova app on Android.

Yes, it is possible.
You have to use RSSI and algorithm that you have to choose depending of what you want to achieve.
Please, find my answer here, in order to get more details, especially on BLE technology limitations for distance measurement.

Yes, it is possible and with using a Firmware newer than v538 (you can check your version via the command "AT-VERS?") it is quite easy as well.
SoftwareSerial mySerial(8, 9); // RX, TX
// Connect HM10 Arduino Uno
// Pin 1/TXD Pin 7
// Pin 2/RXD Pin 8
void setup() {
Serial.begin(9600);
mySerial.begin(9600);
}
void loop(){
String message;
if (Serial.available()) {
c = Serial.read();
mySerial.print(c);
}
if (mySerial.available()) {
message = "";
delay(10);
while (mySerial.available()) {
c = mySerial.read();
message = message + c;
}
Serial.println(message);
}
This is the basic code to get a connection with your HM10 [the rx/tx pins might vary]. If you send a "AT" through your serial monitor, the HM10 should give back an "OK" now.
You might need to setup your HM10 as a BLE central device before you can start scanning for Beacons. This is done by sending:
AT-ROLE1 //sets central role
AT-IMME1 //should work without prior activation
AT-RESET //restarts the HM10
After that, if you send "AT-DISI?" through the serial monitor, the HM10 should start looking for iBeacons and (case it finds one) give back the following [the P´s are placeholders]:
OK+DISC[P0:P1:P2:P3:P4]
This message contains the POWER (sending signal power) and RSSI (recieved signal strength) of the iBeacon, from which the distance to the beacon can be deducted.
The last 2 digits of P3 contain the POWER of the iBeacon, P4 is the RSSI value.
[note: the 2 Power digits are hex values, you need to convert them into decimal values first --- the number should be somewhere around 190]
The most common way to measure distance between the Beacon (as far as I know) is:
distance = 10 ^ ((POWER-RSSI) / 10n) [n is between 2 and 4, I use 2]
:) I hope that helps and good luck on your project.

Related

Problems sending SPI Data from STM32 to arduino

I'm trying to learn how to communicate via SPI with STM32 but I've run into some problems.
The first step i took was to implement SPI communications using two arduino unos: the master writes a byte and the slave responds with another byte according to the input (when the master sends anything, triggering the exchange). Everything worked as it should to the best of my knowledge.
The second step is the one I'm stuck at which is to replace the master arduino with a NUCLEO-F767ZI board. I've set up SPI1 using the auto generated code for now, and I've set it up with what I think are the default options. In the main, I send a single byte to the arduino, and this is where the problem starts:
By using the serial port in the arduino I can see that it does receive data, but usually bit shifted. So if I send a 16, i usually get a 32 or other power of two in the arduino (see attached image)
I'm using clock polarity 0 and clock phase 0 on both microcontrollers (so clock idle on low and sampling on the rising edge). Just to be sure I've tried all possibilities but to no avail, it still doesn't work properly, and I don't really know why. Another thing I considered was that perhaps the clock is running too fast (the peripheral clock is set to 16 MHz), but if I change the prescaler to anything other than SPI_BAUDRATEPRESCALER_2, i stop getting any data on the arduino, only 0s, which I find odd, I would expect it to work just the same if only the master controls the clock.
Just for completeness, here are the spi settings I'm using:
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_HARD_OUTPUT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
The arduino slave code (I've removed the reply part for now):
void setup (void)
{
pinMode(MISO, OUTPUT);
Serial.begin(115200);
// turn on SPI in slave mode
SPCR |= _BV(SPE);
// turn on interrupts
SPCR |= _BV(SPIE);
//Check arduino SPI settings, outputs 11000000, so CPHA and CPOL = 0
Serial.println("SPCR");
Serial.println(SPCR,BIN);
} // end of setup
void loop(void){
}
// SPI interrupt routine
ISR (SPI_STC_vect)
{
byte c = SPDR;
Serial.println(c);
}
}
STM32 master code (ommiting irrelevant parts):
MX_SPI1_Init();
uint8_t data = 16;
while (1)
{
HAL_SPI_Transmit(&hspi1, &data, 1, 100);
HAL_Delay(500);
}
Does anyone have a clue as to why this could be happening? I've found nothing on the prescaler issues and all bitshifting issue posts say that the problem is with clock phase or polarity discrepancies, which I've verified is not.
Thanks in advance
SPI clock rate input to Atmega328P should be lower than Fosc/4
SPI requires the use of nCS wire. An SPI slave will reset it's logic on deassertion of nCS, but if nCS is always at a low level - any missed clock pulse would propagate to the next transfer, shifting the data.
Stm32F7 has NSSP: NSS pulse management - the option for issuing CLK pulse between data bytes. To deassert nCS pin between larger transfers SPI shoud either be disabled and then reenabled before the next transfer, or nCS management should be implemented in the software. In a later case make sure to deassert nCS only after all CLK pulses are completed.
Arduino UNO have Atmega powered from 5V, Stm32 is powered from 3V (on some boards it's 3.3V). Logic high input minimum for the Atmega328 is 0.6VCC, 5V * 0.6V = 3V, wich is on the edge. See this question
A scope would help a lot to solve such cases.

Wire Library - just the first byte device address is being transmitted

I am starting to study the Wire library (no previous Arduino Wire library experience), I read some info taken from here.
As you all know, this really simple example changes the value of a AD5171 digital potentiometer via I2C. Written by Nicholas Zambetti and Shawn Bonkowski, demonstrates use of the Wire library.
I just copied and reduced the code below a little from the example. I am an experienced assembler and C/C++ programmer and hardware developer/designer. Although several I2C devices like DS3231 RTC, etc. work fine using standard Arduino libraries, the mentioned example doesn't work for me in my working NANO board. What am I doing wrong?
This code should transmit:
first the I2C protocol device address - Start / 8 + 1bits
test instruction data byte
variable 1 test byte constantly incremented
I2C Stop condition
The only byte I can see in my oscilloscope is just the first one (please see picture below). The 2 data bytes are not being transmitted. If I reduce the transmission to just the step #2 instruction single data byte, the same result is shown.
#include <Wire.h>
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
}
byte val = 0;
void loop()
{
Wire.beginTransmission(44); // transmit to device #44 (0x2c)
Wire.write(byte(0x55)); // sends instruction byte
Wire.write(val++); // sends potentiometer value byte
Wire.endTransmission(); // stop transmitting
delay(50); // some time delay for my oscilloscope
}
This is what this code produces:
I see transferred data as 01011000 1. I hope the is right decoded. Why you not zoom it more for better reading? It is hard see data levels on raising clock edges. This match to address 44, 0x2C . As you can also see that you get NACK on the end of address octet. So this means no device with transmitting address is on the bus.
You can get error code about sending process from endTransmission function as return int. Send this value to serial monitor.
Error codes you can see in arduino documentation
uint8_t err;
err= Wire.endTransmission(); // stop transmitting and get status
You can also use sketch i2c_scanner from arduino Wire examples to discovery right address of your device.

Android Things I2C read from arduino 3v3

I try to communicate, read and write, from Arduino - slave - to RPi - master - with Android Things.
If i R/W, with a level converter, from RPi to Arduino 5v (16Mhz), everything works fine.
So i decide to eliminate the level converter, and use a 3v3 Arduino mini pro (8Mhz).
The write works fine, but when i try to read from the Arduino, the signal stops.
5v_16Mhz
After the Setup to 9, 0 address, and reads to 9, the signal still low and received the data. No problem.
3v3_8Mhz
After the Setup to 9, 0 address, and read to 9, the signal goes high and the data stop.
I used the same example for the Slave:
#include <Wire.h>
byte RFID[20] = {9,8,7,6,5,4,3,2,1,1,2,3,4,5,6,7,8,9,1,2};
void setup() {
Wire.begin(8); // join i2c bus with address #8
Wire.onRequest(requestEvent); // register event
Wire.onReceive(receiveEvent); // register event
Serial.begin(115200); // start serial for output
pinMode(13, OUTPUT);
}
void loop() {
delay(100);
}
// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent() {
Serial.println("Master ask");
digitalWrite(13, HIGH);
delay(250);
Wire.write(RFID, 20);
digitalWrite(13, LOW);
}
// function should be executes whenever data is received from master
// this function is registered as an event, but it's called every time the RPi
// call the Device.
void receiveEvent(int howMany) {
while (0 < Wire.available()) {
byte RTC_syn = Wire.read(); // receive byte
Serial.println(RTC_syn);
}
}
I really don't know how drives the signal high...
Someone can help me?
If i R/W, with a level converter, from RPi to Arduino 5v (16Mhz), everything works fine.
So i decide to eliminate the level converter, and use a 3v3 Arduino mini pro (8Mhz).
The write works fine, but when i try to read from the Arduino, the signal stops.
This is because level converter you had in the 5V/3.3V version does more than shift the voltage. It also acts as a nice high-impedance buffer between the two devices that helps keep the signal driven and avoids loading effects.
Without the buffer, your bus is likely experiencing a bit of loading. You can try to combat this by adding stronger pull-up resistors. The RPi3 has 1.8k pull-up resistors on the I2C lines, which generally works but can be marginal depending on the input impedance of the slave device. The Arduino Mini has pads to install I2C pull-ups but there are none by default.
The recommended pull-up resistance for a pure 3.3V I2C bus is closer to 1k, so you likely just need to add some stronger pull-ups between SCL/SDA and +3.3V. Anything you add will be in parallel to the RPi3 resistors so factor that into your calculation. For example, adding 4.7k resistors brings the effective resistance down to about 1.3k.
If you are unable to solve it with pull-ups, you can achieve the same buffer effect without level translation by using a line driver IC (random example).
If the level converter works, you should stick with it.
Communication protocols like I2C encode data into a series of logic HIGH and logic LOW signals. What does HIGH / LOW mean? It depends on the devices. For the majority of embedded devices, logic LOW will be ground, 0V.
For Arduinos and Raspberry Pis, the source voltage is different (3.3V versus 5V). This difference can lead to several potential issues.
The 5V signal is too high for the Arduino to handle, causing the Arduino to stop working or reboot
The 3.3V signal is not strong enough to be interpreted as logic HIGH. Embedded devices have circuits that round signals to HIGH/LOW, and the thresholds may not be entirely even. A 5V input may only accept 4.5V or higher, interpreting everything else as LOW or in an indeterminate state.

Unable to get Data from Serial Device using Arduino

I am trying to read the data from a Ultra Sonic Fuel Sensor(the link).The Baud rate of this device is 9600.The device basically sends data at regular time intervals.I am able to read the output in the PC using Terminal software.Given below is a sample.
Eg:*XD,205B,00,0000,0031,0000,0000,null#
I am trying to connect this device to Arduino through serial port provided in the device and when I see the Serial Monitor,the output is not correct.Given below is the sample.
5320215115451166102572432302302432302302302302432303816623024323023023023024323023023023051822281141463
String incoming_char; // Will hold the incoming character from the Serial Port.
void setup()
{
//Initialize serial ports for communication.
Serial.begin(9600);
Serial1.begin(9600);
Serial.println("Starting Communication with Fuel Sensor");
}
void loop()
{
//If a character comes in from the cellular module...
if(Serial1.available() >0)
{
incoming_char=String(Serial1.read()); // Get the character from the cellular serial port.
Serial.print(incoming_char); // Print the incoming character to the terminal.
}
}
The Arduino is powered from USB and the Device from a 12V supply.
The voltage levels from the device Tx-GND=-5.44V,Rx-GND=-8.22V.
I initially thought the the issue might be because of the voltage range and made a voltage divider circuit and fed Arduino the proportionate voltage.Even that is not working.
So,what is the thing which is going wrong ?Please guide me.
Since you are using Serial1 I am assuming you are using an Arduino Mega?
From your question I would say the issue isn't voltage etc. but more likely to be how you are reading the data. You are assuming that the sensor will be returning char values. Are there any specifications on what is being returned?
I created a similar project using an Arduino. Except my Ultrasonic device was used as a range finder. There are details here. As you can see in the code the range is returned from the sensor as a two byte integer.
You will need to find out what the what the Ultra Sonic Fuel Sensor is returning and read in a similar fashion.
allright i would start by suggesting that you connect this to an analog pin to read. you will have to find the ratio between the fuel hight and voltage by measuring and dividing. then insert the multiplication in the code and you are set it will look like the hight instead of just a voltage
This is just a wild guess since I don't own an Arduino Mega (I have Duemilanove and Uno), but I've worked on projects wherein I've encountered issues similar to what you have. Sometimes adding a delay() on your void loop() block helps and gives it enough time for the arduino to read the bytes from the buffer. For 9600 baud rate, it usually takes about 1 ms to read 1 byte so adding a delay is necessary.
void loop()
{
//If a character comes in from the cellular module...
if(Serial1.available() >0)
{
incoming_char=String(Serial1.read()); // Get the character from the cellular serial port.
Serial.print(incoming_char); // Print the incoming character to the terminal.
}
delay(100);
}
Thank you all ! for your Value inputs.The problem was, I was trying to connect RS232 Serial(Works with Negative Voltages) to TTL serial interface(Works with 0 to some Positive Voltages) used in Arduino. Apparently,I was supplying negative voltages to Arduino whereas it was expected to give Positive voltages. So, got a RS232-to-TTL connector and it worked,finally.

Two port receive using software serial on Arduino

i am having trouble getting data from two sensors using two software serial ports with an arduino board. I noticed a similar question might have been asked before but the answers suggest it can't be done and I know fully well it can based on the example here (http://arduino.cc/en/Tutorial/TwoPortReceive)!
I am using an arduino ethernet. The devices I am trying to get data from include a GPS and an IMU both from sparkfun.
I can get data from either devices using just on software serial port but as soon as I add the second software serial port, neither ports will work. I can't use the hardware serial port because that is being used byt another device.
My code is exactly similar to the example:
#include <SoftwareSerial.h>
SoftwareSerial portOne(7,8);
SoftwareSerial portTwo(5,6);
void setup()
{
Serial.begin(9600);
portOne.begin(9600);
portTwo.begin(9600);
}
void loop()
{
portOne.listen();
while (portOne.available() > 0) {
char inByte = portOne.read();
Serial.write(inByte);
}
delay(500);
portTwo.listen();
while (portTwo.available() > 0) {
char inByte = portTwo.read();
Serial.write(inByte);
}
Serial.println();
}
Anyone with any ideas?
This code will not work, or will work poorly if it works at all. SoftwareSerial only has one internal buffer. Yes, you can have multiple SoftwareSerial objects in existence, but only one of them controls the internal buffer. When any RX pin gets asserted, that generates an interrupt, but only the listen()ing RX pin gets checked for a start bit.
What's really needed is the ability to check on multiple pins when an interrupt comes along from the start bit. Then you'd have to set up pointers to the appropriate data structures. It would be complicated, but possible.
Or maybe just give up on interrupt-driven reception, and spin on checking both/all of the RX pins, and start the receive based on the pin you see. Be forwarned that this code has much hair, and you WILL need an oscilloscope to make it work.
I'm having a similar problem, which is why I found your sensor. After talking it over with my co-workers, we've decided to read our sensors in rotating order. Our sensors report the current state of the sensor, and not specific events, so it's okay if we lose some reports. So we'll read from port 1, then read from port 2, then port 1, etc. Our sensors spit out lines of text, so we know when to switch to the next sensor.
The referenced example only actively listens to one port at a time. The recommended solution would be to upgrade to an Arduino Mega (https://www.sparkfun.com/products/11061) which has 4 hardware serial ports.
In order to simultaneously support two software serial ports is going to require a lot of the CPU resources. It also be a difficult design and excessive programming time far outweighing the cost of $58 + shipping.
Looking at you code again it occurs to me that you are immediately checking for characters after your portOne.listen command. At 9600 baud it will take approximately 1ms for the first character to arrive, your while test will have been completed and the portTwo.listen command executed long before the first character arrives.
For testing purposes try adding a 1-2 ms delay after the portOne.listen command and see if you get a character.
As an example (untested and note, if port one is sending characters with no intercharacter gaps, the first while will never fail, preventing reading portTwo characters):
void loop()
{
portOne.listen();
delay(2);
while (portOne.available() > 0) {
char inByte = portOne.read();
Serial.write(inByte);
delay(1);
}
portTwo.listen();
delay(2);
while (portTwo.available() > 0) {
char inByte = portTwo.read();
Serial.write(inByte);
delay(1);
}
Serial.println();
}
Don't use while ......
Use:
{ portOne.listen();
if (PortOne.available() ) {
ricevo = myPort1.read(); }
// delay(2); // ridiculos waiting time
// delay(1); // extra ridiculos waiting time
Than 500 ms is a too big time for switching, no time.....

Resources