iOS Get Link Speed (Router Speed Test) - ios

I want to test speed of connected router(wifi modem) from iOS app.
I've found something here Get link speed programmatically? but could not found sockios.h and ethtool.h
Is it possible to port this code to Objective-C or is there another way?
--
Sorry for the missing info and my poor english.
I want to test link speed (tx rate) between ios device and connected wifi modem.
There was a property named txRate in CWInterface class. I want to get that data in Cocoa Touch.
/*!
* #property
* #abstract Current transmit rate (Mbps) of the CoreWLAN interface.
* #discussion Dynamically queries the interface for the current transmit rate.
*/
#property(readonly) NSNumber *txRate NS_DEPRECATED_MAC(10_6, 10_7);

Finally I've found the solution.
#include <ifaddrs.h>
#include <net/if.h>
+ (double)getRouterLinkSpeed
{
BOOL success;
struct ifaddrs *addrs;
const struct ifaddrs *cursor;
const struct if_data *networkStatisc;
double linkSpeed = 0;
NSString *name = [[NSString alloc] init];
success = getifaddrs(&addrs) == 0;
if (success)
{
cursor = addrs;
while (cursor != NULL)
{
name=[NSString stringWithFormat:#"%s",cursor->ifa_name];
if (cursor->ifa_addr->sa_family == AF_LINK)
{
if ([name hasPrefix:#"en"])
{
networkStatisc = (const struct if_data *) cursor->ifa_data;
linkSpeed = networkStatisc->ifi_baudrate;
}
}
cursor = cursor->ifa_next;
}
freeifaddrs(addrs);
}
return linkSpeed;
}

You can use NSURLConnection to connect to your test server and download a preset file of something like 1 MB. Use the NSURLConnection delegate -connection:didReceiveData: and -connectionDidFinishLoading:to track the download 'so far' and compute the download speed from that.

There is currently no official (or Apple approved) way to get LinkSpeed on iOS. There were loop holes in the past which were closed unfortunately.
The most similar metric you can use to estimate LinkSpeed is measure wifi speed by sending UDP packets on the local network and measuring their sending rate. This is called IP packet sending bit rate and is defined in this ITU standard https://www.itu.int/rec/T-REC-Y.1540/en
The iOS implementation of that wifi speed measurement is in our iOS SDK which you can find here:
https://github.com/speedchecker/speedchecker-sdk-ios
This implementation is the closest you can get to estimate router wifi speed without actually placing any payload files on the router itself.

Related

Esp32 Bluetooth Low Energy get RSSI strength from iOS & Android

I need to setup my Esp32-D1-Mini to read RSSI from both my iPhone and Nexus 5x (not at the same time of course, in other words I'd like it to work with both operating systems and read RSSI from them continously).
I've managed to make it work with Bluetooth Classic but that only works with Android OS smartphones and I need to have it work with iOS devices as well, so I had to switch to using BLE and this looks much more complicated.
The Esp32 is setup to work as a Server which anyone can connect to.
It is supposed to wait for a device to connect to it and as soon as that device is connected the Esp32 should start reading RSSI strength continously (with a 1 second delay) until the other device disconnects then enter back in "sleep mode" and wait for another device to connect to it.
The code I have right now has a few problems which I struggle to solve:
It won't read any RSSI whatsoever from my iPhone, after it connects to the Esp32 using the LightBlue App
After my Android phone connects to the Esp32, using the nRF Connect app, it will read the RSSI values just once, instead of continuing to read them until the phone disconnects or it loses signal to the Esp32.
The iPhone will not reveal its Mac adress after connecting (no mac adress appears at all) which in response won't let my Esp32 read any RSSI values from the iPhone and from what I've understood I need to request pairing from my Esp32 when the iPhone wants to connect to it in order for the iPhone to reveal its MAC Address and get RSSI from it (but I didn't find any example of how to achieve that, at least not by using Arduino), that is because the Esp32 first needs a MAC Adress of the device I want to read RSSI from, being it already connected to the Esp32 or not; the iphone does not reveal its Mac Adress after connecting so I guess I have to force it to pair when any iOS device tries to connect to the Esp32 in order to fetch their Mac Address and read their rssi.
The RSSI values start from 0 when they are read from my Android phone and they go up; I've managed to write the code first time using Bluetooth Classic and I really liked the way the RSSI would show, which would be 0 when standing close to the Esp32 (after connecting to it) and when getting away decreasing to -5, -10, etc. I'd like to read the rssi in the same way if possible, not from 0 up.
See my BT Classic Code at the bottom.
This is my current code (I've used the Esp32 Ble Client example as a starting point):
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLEScan.h>
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
const int PIN = 2;
bool deviceConnected = false;
static void my_gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param) {
Serial.print("RSSI status");Serial.println(param->read_rssi_cmpl.status);
Serial.print("RSSI ");Serial.println(param->read_rssi_cmpl.rssi);
Serial.print("Address ");Serial.println(BLEAddress(param->read_rssi_cmpl.remote_addr).toString().c_str());
}
void setup() {
Serial.begin(9600);
BLEDevice::init("Long name works now");
BLEServer *pServer = BLEDevice::createServer();
BLEService *pService = pServer->createService(SERVICE_UUID);
BLECharacteristic *pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID,BLECharacteristic::PROPERTY_READ|BLECharacteristic::PROPERTY_WRITE);
BLEDevice::setCustomGapHandler(my_gap_event_handler);
pCharacteristic->setValue("Hello World says Neil");
pService->start();
//BLEAdvertising *pAdvertising = pServer->getAdvertising(); // this still is working for backward compatibility
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06); // functions that help with iPhone connections issue
pAdvertising->setMinPreferred(0x12);
BLEDevice::startAdvertising();
pinMode (PIN, OUTPUT);//Specify that Vibration Motor pin is output
}
void loop() { // put your main code here, to run repeatedly:
delay(1000);
}
I bassically want to have the BLE code doing what my BT Classic code does (I don't need help with setting up the distance meassuring and the kalman filter, I think I know how to configure them myself);
I only need help with getting the Esp32 to read the RSSI continously from any iOS & Android devices trying to connect to the Esp32.
Here is my Bluetooth Classic Code (working well but with Android OS devices only):
#include "esp_bt_main.h"
#include "esp_gap_bt_api.h"
#include "esp_bt_device.h"
#include "BluetoothSerial.h" //Header File for Serial Bluetooth, will be added by default into Arduino
#include "esp_gap_bt_api.h"
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "Kalman.h"
// My function prototypes
void gap_callback (esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param);
void spp_callback (esp_spp_cb_event_t event, esp_spp_cb_param_t *param);
//Creates the variables:
double measurement, filteredMeasurement;
Kalman myFilter(0.125,32,1023,0); //suggested initial values for high noise filtering
// this->q = process_noise;
// this->r = sensor_noise;
// this->p = estimated_error;
// this->x = intial_value; //x will hold the iterated filtered value
uint8_t link_master;
BluetoothSerial SerialBT;
int rssi = 0; //RSSI
/* Kalman filter variables */
double q; //process noise covariance
double r; //measurement noise covariance
double x; //value
double p; //estimation error covariance
double k; //kalman gain
//distance = pow(10, ((refOneMeter - recvRSSI) / (10 * estPathLossExp))) //formula for distance meassurement
// we need variables to hold refOneMeter, recvRSSI, and estPathLossExp
byte addr[6] = {0, 0, 0, 0, 0, 0}; //to keep MAC address of the remote device , 8 bit value
static int PAIRING_VARIANT_PIN; //The user will be prompted to enter a pin or an app will enter a pin for user
struct read_rssi_delta_param;
struct esp_bt_gap_cb_param_t::read_rssi_delta_param read_rssi_delta; //read rssi parameter struct
esp_bd_addr_t bda; //remote bluetooth device address
int8_t rssi_delta; //rssi delta value range -128 ~127, The value zero indicates that the RSSI is inside the Golden Receive Power Range, the Golden Receive Power Range is from ESP_BT_GAP_RSSI_LOW_THRLD to ESP_BT_GAP_RSSI_HIGH_THRLD
esp_err_t esp_bt_gap_read_rssi_delta(esp_bd_addr_t remote_addr); //This function is called to read RSSI delta by address after connected. The RSSI value returned by ESP_BT_GAP_READ_RSSI_DELTA_EVT.
BluetoothSerial ESP32Mini_Bluetooth; //Object for Bluetooth
//ESP32Mini_Bluetooth_GAP_READ_RSSI_DELTA_EVT; //read RSSI event
//ESP_BT_GAP_DEV_PROP_RSSI; // Received Signal strength Indication, value type is int8_t, ranging from -128 to 127
//ESP_BT_GAP_RSSI_LOW_THRLD; // Low RSSI threshold
//ESP_BT_GAP_RSSI_HIGH_THRLD; // RSSI threshold. High RSSI threshold
//esp_bd_addr_t bda; //remote bluetooth device address
//esp_bt_status_t stat; //read rssi status
const int PIN = 32;
const int CUTOFF = -60;
int incoming;
int best;
float distance = 0.0;
void setup() {
ESP32Mini_Bluetooth.setPin("4321"); //This should solve the Secured Pin Connection
SerialBT.begin();
Serial.begin(9600); //Start Serial monitor in 9600 ; this is the line where it initialize serial to 9600 baud speed
// this->q = process_noise;
// this->r = sensor_noise;
// this->p = estimated_error;
// this->x = intial_value; //x will hold the iterated filtered value
// float temp1 = ((-6) - (rssi));
// float temp2 = (temp1 / 100);
// distance= pow(10,temp2);
// distance = pow(10, (-6 - rssi) / (100));
ESP32Mini_Bluetooth.begin("Esp32-Mini"); //Name of your Bluetooth Signal
Serial.println("Bluetooth Device is Ready to Pair");
pinMode (PIN, OUTPUT);//Specify that Vibration Motor pin is output
esp_bt_gap_register_callback (gap_callback); //register the RSSI callback function by calling this line
//register SPP service callback to get remote address:
SerialBT.register_callback(spp_callback);
// //This is Legacy Pairing Code
//ESP_BT_GAP_PIN_REQ_EVT //Legacy Pairing Pin code request
//ESP_BT_GAP_CFM_REQ_EVT //Simple Pairing User Confirmation request.
//ESP_BT_GAP_KEY_NOTIF_EVT //Simple Pairing Passkey Notification
//ESP_BT_GAP_KEY_REQ_EVT //Simple Pairing Passkey request
}
void loop() {
delay(100);
if (SerialBT.hasClient()) { //this is where we get and handle RSSI value
//when we need RSSI call this:
esp_bt_gap_read_rssi_delta (addr); //now variable rssi contains RSSI level
byte b = rssi; //etc....
//reads measurement and filter it
measurement = (double) rssi; //read new value from rssi
filteredMeasurement = myFilter.getFilteredValue(measurement);
float temp1 = (3) - (rssi);
float temp2 = (temp1 / 100);
distance = pow(10,temp2);
if (rssi < -10)
{
digitalWrite(PIN, HIGH);
//ESP32Mini_Bluetooth.println("Vibration Motor ON");
//Serial.print ("PIN turned ON");
}
if (rssi > -10)
{
digitalWrite(PIN, LOW);
//ESP32Mini_Bluetooth.println("Vibration Motor OFF");
//Serial.print ("PIN turned OFF");
}
//ESP32Mini_Bluetooth.print("RSSI: "); //println add linefeed for end of printed string
//ESP32Mini_Bluetooth.println(rssi); //println add linefeed for end of printed string
//ESP32Mini_Bluetooth.print(", ");
//ESP32Mini_Bluetooth.println(filteredMeasurement);
ESP32Mini_Bluetooth.print(rssi);
ESP32Mini_Bluetooth.print(", ");
ESP32Mini_Bluetooth.println(distance);
//So building up the serial, we have filtered: <value> TAB
//we are adding filtered: <value> TAB distance: <value> TAB rssi: <value>
Serial.print ("filtered:");
Serial.print (filteredMeasurement);
Serial.print ("\t distance:");
Serial.print (distance);
Serial.print ("\t rssi:");
Serial.print (rssi);
delay (1000); //DELAY OF 1 SECONDS
}
else
{
// Disconnected state
digitalWrite(PIN, LOW);
// Serial.println ("Disconnected. PIN turned OFF");
Serial.println (rssi);
delay(1000); // wait 1s
}
if (ESP32Mini_Bluetooth.available()) //Check if we receive anything from Bluetooth // is telling that BT has received some data and it need to be processed
{
incoming = ESP32Mini_Bluetooth.read(); //Read what we recevive
Serial.print("Received:"); Serial.println(incoming);
digitalWrite(PIN, best > CUTOFF ? HIGH : LOW);
}
}
//RSSI callback function
void gap_callback (esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param)
{
if (event == ESP_BT_GAP_READ_RSSI_DELTA_EVT)
{
rssi = param->read_rssi_delta.rssi_delta; // it checks it has connection
Serial.print("\t RSSI Delta: ");
Serial.println (param->read_rssi_delta.rssi_delta);
}
}
//SPP service callback function (to get remote MAC address)
void spp_callback (esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
{
if (event == ESP_SPP_SRV_OPEN_EVT)
memcpy(addr, param->srv_open.rem_bda, 6);
}

How to implement ticker callback at 100 micro seconds for ESP8266?

I have an ESP8266 NodeMCU 12E development board and I'm using the Arduino IDE. I'm trying to use a Ticker.h to sample an analog input consistently at a frequency of 10khz, which is one sample every 100us. I noticed that Ticker sampler; sampler.attach(0.0001,callbackfunc); didn't work because attach() won't take the value 0.0001.
So then I wrote the following code based on some guides that I saw:
#include <ESP8266WiFi.h>
#include <Ticker.h>
bool s = true;
void getSample()
{
s = !s;
}
Ticker tickerObject(getSample, 100, 0, MICROS_MICROS);
const char *ssid = "___"; // Change it
const char *pass = "___"; // Change it
void setup()
{
Serial.begin(115200);
Serial.println(0); //start
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, pass);
tickerObject.start();
}
void loop()
{
if(s == true)
{
Serial.println("True");
}
else
{
Serial.println("False");
}
}
However, this did not compile because tickerObject.start() method did not exist. So what I did next was:
Download the latest ticker package as a zip file
Unzip the package from point 1
Made a back up of C:\Users\john\Documents\ArduinoData\packages\esp8266\hardware\esp8266\2.5.0-beta2\libraries\Ticker
Replaced the folder mentioned in point 3 with the Ticker folder in point 2.
Restarted my Arduino IDE
Compiled and ran the code
Opened up the Serial Monitor
However, when I inspect the serial monitor, all it prints is "True". I was expecting the value s to toggle between true and false at a 10khz frequency.
What did I do wrong?
From the documentation of this library:
The library use no interupts of the hardware timers and works with the micros() / millis() function.
This library implements timers in software by polling the micros() and millis() functions. It requires the update() method to be called in loop().
So the start of loop() should be:
void loop()
{
tickerObject.update();
if(s == true)
I'm trying to use a Ticker.h to sample an analog input consistently at a frequency of 10khz
It is worth a go but this is a software based solution that is prone to jitter depending on how often the event loop can be called.

How to decrease memory usage on Arduino Uno

I am using a clone of Arduino UNO, Dccduino and I have problem with the memory.Sketch uses 25,114 bytes (77%) of program storage space. Maximum is 32,256 bytes. Global variables use 1,968 bytes (96%) of dynamic memory, leaving 80 bytes for local variables. Maximum is 2,048 bytes. Low memory available, stability problems may occur.
Is there any way to reduce the memory about 20% if not I think I have to buy Arduino Mega
Here is the code:
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include "RTClib.h"
#include <GPRS_Shield_Arduino.h>
#include <SoftwareSerial.h>
// Data wire is plugged into port 3 and 2 on the Arduino
#define ONE_WIRE_BUS_1 3 // Many sensors on pin 3
#define ONE_WIRE_BUS_2 2 // Many sensors on pin 2
#define TEMPERATURE_PRECISION 9 // Lower resolution
#define PIN_TX 7
#define PIN_RX 8
#define BAUDRATE 9600
#define PHONE_NUMBER "xxxxxxxxxxxxx"
GPRS gprsTest(PIN_TX, PIN_RX, BAUDRATE); //RX,TX,PWR,BaudRate
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire1(ONE_WIRE_BUS_1);
OneWire oneWire2(ONE_WIRE_BUS_2);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors1(&oneWire1);
DallasTemperature sensors2(&oneWire2);
int numberOfDevices1; // Number of temperature devices found on pin 3
int numberOfDevices2; // Number of temperature devices found on pin 2
DeviceAddress tempDeviceAddress1; // We'll use this variable to store a found device address for bus 3
DeviceAddress tempDeviceAddress2; // We'll use this variable to store a found device address for bus 2
File myFile;
RTC_DS3231 rtc; // Create a RealTimeClock object
void setup(void)
{
// start serial port
#ifndef ESP8266
while (!Serial); // for Leonardo/Micro/Zero
#endif
Serial.begin(9600);
delay(3000);
Serial.println(F("Dallas Temperature IC Control Library Demo"));
Serial.print( F("Initializing SD card..."));
if (!SD.begin(4)) {
Serial.println(F("\ninitialization failed!"));
return;
}
Serial.println(F("initialization done."));
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
if (rtc.lostPower()) {
Serial.println("RTC lost power, lets set the time!");
// following line sets the RTC to the date & time this sketch was compiled
//rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// This line sets the RTC with an explicit date & time, for example to set
// January 21, 2014 at 3am you would call:
// rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
}
/* while(!gprsTest.init()) { //gprs init
delay(1000);
Serial.print(F("init error\r\n"));
Serial.println(F("gprs init success"));*/ It takes 20% of dynamic memory so i cant use it
}
Serial.println(F("start to call ..."));// Call when device will start
gprsTest.callUp(PHONE_NUMBER);
Serial.println("start to send message ...");
gprsTest.sendSMS(PHONE_NUMBER, "Hi device is ON"); //define phone number and text
// Start up the library
sensors1.begin();
sensors2.begin();
// Grab a count of devices on the wire
numberOfDevices1 = sensors1.getDeviceCount();
numberOfDevices2 = sensors2.getDeviceCount();
// locate devices on the bus
Serial.print(F("Locating devices..."));
Serial.print(F("Found "));
Serial.print(numberOfDevices1, DEC );
Serial.print(F("+"));
Serial.print(numberOfDevices2, DEC );
Serial.println(F(" devices."));
// report parasite power requirements
Serial.print("Parasite power is: ");
if (sensors1.isParasitePowerMode()) Serial.println(F("Sensors 1 ON"));
else Serial.println(F("\nSensors 1 OFF"));
if (sensors2.isParasitePowerMode()) Serial.println(F("Sensors 2 ON"));
else Serial.println(F("Sensors 2 OFF"));
// Loop through each device, print out address for pin 3
for (int i = 0; i < numberOfDevices1; i++)
{
// Search the wire for address
if (sensors1.getAddress(tempDeviceAddress1, i))
{
Serial.print(F("Found device "));
Serial.print(i, DEC);
Serial.print(F(" with address: "));
printAddress(tempDeviceAddress1);
Serial.println();
Serial.println(F("\n"));
// set the resolution to TEMPERATURE_PRECISION bit (Each Dallas/Maxim device is capable of several different resolutions)
sensors1.setResolution(tempDeviceAddress1, TEMPERATURE_PRECISION);
} else {
Serial.print(F("Found ghost device for pin 3 at "));
Serial.print(i, DEC);
Serial.print(F(" but could not detect address. Check power and cabling"));
}
}
// Loop through each device, print out address for pin 2
for (int i = 0; i < numberOfDevices2; i++)
{
// Search the wire for address
if (sensors2.getAddress(tempDeviceAddress2, i))
{
Serial.print(F("Found device "));
Serial.print(i + numberOfDevices1, DEC);
Serial.print(F(" with address: "));
printAddress(tempDeviceAddress2);
Serial.println();
Serial.println(F("\n"));
// set the resolution to TEMPERATURE_PRECISION bit (Each Dallas/Maxim device is capable of several different resolutions)
sensors2.setResolution(tempDeviceAddress2, TEMPERATURE_PRECISION);
} else {
Serial.print(F("Found ghost device for pin 2 at "));
Serial.print(i, DEC);
Serial.print(F(" but could not detect address. Check power and cabling"));
}
}
}
void loop(void)
{
// call sensors1.requestTemperatures() to issue a global temperature
// request to all devices on the bus
Serial.print(F("Requesting temperatures to pin 3..."));
sensors1.requestTemperatures(); // Send the command to get temperatures for pin 3
Serial.println(F("DONE"));
myFile = SD.open("test1.txt", FILE_WRITE); //open file
// Loop through each device , print out temperature data for pin 3
for (int i = 0; i < numberOfDevices1; i++)
{
// Search the wire for address
if (sensors1.getAddress(tempDeviceAddress1, i))
{
// Output the device ID
Serial.print(F("Temperature for device: "));
Serial.println(i, DEC);
// It responds almost immediately. Let's print out the data
printTemperature1(tempDeviceAddress1);// Use a simple function to print out the data
Serial.print(F("\n"));
}
delay(4000);
//else ghost device! Check your power requirements and cabling
}// End forloop for pin 3
if (numberOfDevices2 != 0) {
Serial.print(F("Requesting temperatures to pin 2..."));
sensors2.requestTemperatures(); // Send the command to get temperatures for pin 2
Serial.println(F("DONE"));
}
// Loop through each device for pin 2, print out temperature data
for (int i = 0; i < numberOfDevices2; i++)
{
// Search the wire for address
if (sensors2.getAddress(tempDeviceAddress2, i))
{
// Output the device ID
Serial.print(F("Temperature for device: "));
Serial.println(i + numberOfDevices1, DEC);
// It responds almost immediately. Let's print out the data
printTemperature2(tempDeviceAddress2);// Use a simple function to print out the data
Serial.print(F("\n"));
}
else Serial.print(F("ghost device! Check your power requirements and cabling"));
delay(4000);
} //End forloop for pin 3
myFile.close(); // Should I close it?
}// End loop()
void printAddress(DeviceAddress deviceAddress) // function to print a device address
{
for (uint8_t i = 0; i < 8; i++)
{
if (deviceAddress[i] < 16) Serial.print(F("0"));
Serial.print(deviceAddress[i], HEX);
}
}
void printTemperature1(DeviceAddress deviceAddress1) // function to print the temperature for a device (pin 3)
{
float tempC = sensors1.getTempC(deviceAddress1);
Serial.print("Temp C: ");
Serial.print(tempC);
if (myFile)
{
Serial.println(F("\nWriting to test.txt..."));
myFile.print(F("C: "));
myFile.print(tempC);
print_time(); // Call print_time() function to print time on file
myFile.print(F("\n"));
Serial.print(F("Done!"));
}
else Serial.print(F("Error opening file 1"));
Serial.println("\n");
}
void printTemperature2(DeviceAddress deviceAddress2) // function to print the temperature for a device (pin 2)
{
float tempC = sensors2.getTempC(deviceAddress2);
Serial.print(F("Temp C: "));
Serial.print(tempC);
if (myFile)
{
Serial.print(F("\nWriting to test.txt..."));
myFile.print(F("C: "));
myFile.print(tempC);
print_time(); // Call print_time() function to print time on file
myFile.print(F("\n"));
Serial.print(F("Done!"));
} else Serial.print(F("Error opening file 2"));
Serial.println("\n");
}
void print_time() { // print time function
DateTime now = rtc.now();
Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();
myFile.print(now.year(), DEC);
myFile.print('/');
myFile.print(now.month(), DEC);
myFile.print('/');
myFile.print(now.day(), DEC);
myFile.print(now.hour(), DEC);
myFile.print(':');
myFile.print(now.minute(), DEC);
myFile.print(':');
myFile.print(now.second(), DEC);
myFile.println();
}
I'm doing more than that for a system in my barn - SD card, RTC, LCD display, GPRS modem, radio communication with other devices, controlling pumps based on programmed timing by season, rain sensors, float sensors, temp sensors, voltage sensors, etc. Here are some things I've found:
All string literals should be replaced by F() macro calls and or native string functions working on flash. So, strcpy_P(string1, PSTR(string2)), strcat_P(string1, PSTR(string2)) kind of calls.
Turn lots of accesses to devices into function calls that contain any data structures needed for those calls. Your arduino will work harder adding and removing stack and stack frames, but the data structures will be removed from the stack when the function is done, and machine cycles are much cheaper on Arduino than RAM. So, separate your temperature reading code in a separate function from your file-writing. Return the float, then send that float to your SD-writing function.
Hide all of your Serial code in debug_print code instead. So, you'll use debug_print calls when debugging, and they all disappear completely from your production code.
Make sure you're only calling the SD code in subroutines, and instantiating the actual FAT code in those subroutines as needed, not as a big global.
There are a number of different SD libraries, some are cheaper (memory-wise) than others. Shop around.
Use one of the freeMemory variants to decide if you have the memory available before calling one of those RAM-hungry SD calls. If you don't have enough RAM at the time, you may want to implement some kind of circular buffer in EEPROM to store messages to be written to SD when you do have the RAM available.
Use booleans and bytes instead of ints when possible, and consider using bit fields for flags to save even more RAM. Are you really going to have up to 32,000 devices on your temperature buses? You can get 255 in a byte.
I think I've seen this code before on another site.
From your code I assume you're making a temperature logger and you want to log the data on the SD card.
Most of your code is redundant if you use the DS1307RTC.h library and the Time.h library. DS1307RTC is a generic RTC library. With it you don't need OneWire, Wire or SPI and Wire. Software Serial also is unnecessary.
However, I suggest you check out my Arduino DataLogger Library on Github: https://github.com/FreelanceJavaDev/DataLogger
I've pretty much maxed out the memory I saved on my Uno down to 22,680 bytes (70%) of program storage space and 1,237 bytes (60%) of SRAM (Dynamic memory). It automatically configures the RTC and SD card. It makes a CSV file for export to excel for each month it's running organized by date.
I've built several Arduino data loggers in my time, and all of the ones using SD cards have failed because of lack of memory. The SD on its own uses half of the memory available on an ATMega 328. Add to that a couple of libraries for other hardware and you have no memory left at all for your sketch.
I have gone over to 24LC512s. One is normally enough, but you can use up to 4 with different addresses if you want. This is a relatively small amount of memory, but I have found it is always enough. It is too easy to generate megabytes of data which is too large to be analysed. One 24LC512 holds more than enough data for one spreadsheet. The only down side is that you have to use an Arduino to read back the data through the USB.
I use the first two bytes to store the number of records, and the next byte to store the number of bytes per record. (Although in retrospect the latter is not really necessary.) You might think that the first two bytes would “wear out” because they are re-written every time a new entry is made, but this has not happened to me yet. I have had the same Arduino continuously running for 7 years now (uninterrupted apart from a few updates to the sketch), and generating over 1000 records per month, so the first two bytes must have been updated that number of times. I have never had a problem with the first two bytes, and even if I did, it would be cheap enough to replace the 24LC512.
You can even get away with “hot plugging”: I leave the logger running and change over the memory chip for a fresh one so that I can read the data without interrupting the logger. (Read the number of records, then increment it and write the new number and the data.)

How to update a UILabel in realtime when receiving Serial.print statements

I am using a Bluno microcontroller to send / receive data from an iPhone, and everything is working as it should, but I would like to update the text of a UILabel with the real time data that is being printed from the Serial.print(numTicks); statement. If I stop the flowmeter the UILabel gets updated with the most current value, but I would like to update this label in realtime. I am not sure if this is a C / Arduino question or more of a iOS / Objective-C question. The sketch I'm loading on my Bluno looks like the following, https://github.com/ipatch/KegCop/blob/master/KegCop-Bluno-sketch.c
And the method in question inside that sketch looks like the following,
// flowmeter stuff
bool getFlow4() {
// call the countdown function for pouring beer
// Serial.println(flowmeterPin);
flowmeterPinState = digitalRead(flowmeterPin);
// Serial.println(flowmeterPinStatePinState);
volatile unsigned long currentMillis = millis();
// if the predefined interval has passed
if (millis() - lastmillis >= 250) { // Update every 1/4 second
// disconnect flow meter from interrupt
detachInterrupt(0); // Disable interrupt when calculating
// Serial.print("Ticks:");
Serial.print(numTicks);
// numTicks = 0; // Restart the counter.
lastmillis = millis(); // Update lastmillis
attachInterrupt(0, count, FALLING); // enable interrupt
}
if(numTicks >= 475 || valveClosed == 1) {
close_valve();
numTicks = 0; // Restart the counter.
valveClosed = 0;
return 0;
}
}
On the iOS / Objective-C side of things I'm doing the following,
- (void)didReceiveData:(NSData *)data Device:(DFBlunoDevice *)dev {
// setup label to update
_ticks = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
[_tickAmount setText:[NSString stringWithFormat:#"Ticks:%#",_ticks]];
[_tickAmount setNeedsDisplay];
NSLog(#"ticks = %#",_ticks);
}
Basically I would like to update the value of the UILabel while the flowmeter is working.
UPDATE
I just tested the functionality again with the serial monitor within the Arduino IDE, and I got the same if not similar results as to what I got via Xcode and the NSLog statements. So this leads me to believe something in the sketch is preventing the label from updating in real time. :/ Sorry for the confusion.

Getting WIFI Signal strength in iPhone

I know this is a duplicate of many similar questions.But none of them were clear they where not giving proper solutions.My question is how to get WiFi signal strength in iOS devices?. I know it has done using Private API's but I don't know how to use?. Please can anyone help me please?
For ios9+
Register your app as Hotspot helper. (forums.developer.apple.com/message/30657#30657)
#import <NetworkExtension/NetworkExtension.h>
for(NEHotspotNetwork *hotspotNetwork in [NEHotspotHelper supportedNetworkInterfaces]) {
NSString *ssid = hotspotNetwork.SSID;
NSString *bssid = hotspotNetwork.BSSID;
BOOL secure = hotspotNetwork.secure;
BOOL autoJoined = hotspotNetwork.autoJoined;
double signalStrength = hotspotNetwork.signalStrength;
}
Reference:- https://stackoverflow.com/a/32971064/988169
Apple restrict (wireless private api) to use private api to find the strenth of wifi .

Resources