How to implement ESP8266 5 kHz PWM? - esp8266

I need to realise a PWM output with 5 kHz +/- 5%. (Presumably due to a filter circuit into which this feeds over which I have no control.)
Is this realisable with a ESP8266 (ideally with NodeMCU)?
I realise that the software PWM of the ESP8266 has a maximum frequency of 1 kHz while the sigma-delta can be used to implement a PWM with a fixed frequency of about 300 kHz.
So is there a reliable way to achieve 5 kHz? I know some people experimented with the I2S peripheral for waveform output but I am unsure whether it can be used for 5kHz output.
Has anybody looked at into a similar problem before?

The essential code is:
#define qap 2 // Quick As Possible ... Duty cycle only 0, 50, 100%
#define HFreq 5150
#define pPulse D2 // a NodeMCU/ESP8266 GPIO PWM pin
analogWriteRange(qap); analogWriteFreq( HFreq ); analogWrite(pPulse, 1); // start PWM
TL;DR
Just did some crude benchamrks
// had HFreq=126400 with 75 KHz pulse at 80 MHz ESP clock, every 1 sec but proof of evidence lost
nominally with 80 MHz clock got
// 72.24 KHz 361178 2015061929
// 72.23 KHz 361163 2415062390
// 72.23 KHz 361133 2815062824
and
// 141.52 KHz 353809 2009395076
// 141.54 KHz 353846 2409395627
// 141.52 KHz 353806 2809395946
with 160 MHz clock
CAVEATS!!!
1. The duty cycle range is 2!
2. As well the system had no other conditioning, so other timing artifacts were still present from Serial IO etc. In particular instability due to the WDT and WiFi penultimately appeared. (Anyhow, presumably this is an issue only when the ESP8266 is under stress and duress.)
// 141.50 KHz 353754 619466806
// 141.52 KHz 353810 1019467038
// ...
// ad infinitum cum tempore finitum, infinitus est ad nauseum?
// ...
// 141.54 KHz 353857 735996888
//
// ets Jan 8 2013,rst cause:4, boot mode:(1,7)
//
//wdt reset
When using the following code to generate a 5 KHz square wave signal, the considerations above are not an issue and do not occur.
// ------------ test results for 80 MHz clock --------------
//
//
// PWM pulse test
//
// F_CPU: 80000000L
// ESP8266_CLOCK: 80000000UL
// PWM "freq.": 5150
//
//
// connect D1 to D2
//
//
// raw MPU
// frequency count cycle
// 0.00 KHz 1 407976267
// 4.74 KHz 9482 567976702
// 5.00 KHz 10007 727977137
// 5.00 KHz 10006 887977572
// 5.00 KHz 10006 1047978007
// 5.00 KHz 10007 1207978442
// 5.00 KHz 10006 1367978877
// 5.00 KHz 10006 1527979312
// 5.00 KHz 10007 1687979747
// 5.00 KHz 10006 1847980182
// 5.00 KHz 10006 2007980617
// 5.00 KHz 10007 2167981052
// 5.00 KHz 10006 2327981487
// 5.00 KHz 10006 2487981922
// 5.00 KHz 10007 2647982357 ...
//
// crude testing for 5KHz signal
// extracted from:
// highest frequency / shortest period pin pulse generate / detect test
//
// uses raw ESP8266 / NodeMCU V1.0 hardware primitive interface of Arduino IDE (no included libraries)
//
// timing dependencies: WDT, WiFi, I2S, I2C, one wire, UART, SPI, ...
//
// Arduino GPIO 16 5 4 0 2 14 12 13 15 3 1 0 1 2 3 4 5 ... 12 13 14 15 16
// NodeMCU D pin 0 1 2 3 4 5 6 7 8 9 10 3 10 4 9 2 1 ... 6 7 5 8 0
// | | | | | | | | | | |
// a WAKE | | F Tx1 | | Rx2 Tx2 Rx0 Tx0
// k (NO PWM or | | L blue | | | |
// a' interrupt) | S A * H | H | H | | * led's
// s red S D S S M S H
// * C A H C I I C
// L T L S M S
// K A K O O
// └ - - - - └----UART's----┘
// └--I2C--┘ └-----SPI------┘
//
// rules of engagement are obscure and vague for effects of argument values for the paramters of these functions:
// analogWriteRange(qap); analogWriteFreq( HFreq ); analogWrite(pPulse, 1);
//
// http://stackoverflow.com/questions/42112357/how-to-implement-esp8266-5-khz-pwm
//
// system #defines: F_CPU ESP8266_CLOCK
#define pInt D1 // HWI pin: NOT D0 ie. GPIO16 is not hardwared interrupt or PWM pin
#define pPulse D2 // PWM pulsed frequency source ... ditto D0 (note: D4 = blue LED)
#define countFor 160000000UL
#define gmv(p) #p // get macro value
#define em(p) gmv(p) // evaluate macro
#define qap 2 // minimal number of duty cycle levels (0, 50, 100% ) Quick As Possible ...
#define HFreq 5150 //((long int) F_CPU==80000000L ? 125000 : 250000) // ... to minimize time of a cycle period
// max values ^ and ^ found empirically
// had HFreq=126400 with 75 KHz pulse at 80 MHz ESP clock, every 1 sec but proof of evidence lost
#define infoTxt (String) \
"\n\n\t PWM pulse test " \
"\n F_CPU: " em(F_CPU) \
"\n ESP8266_CLOCK: " em(ESP8266_CLOCK) \
"\n PWM \"freq.\": " + HFreq + "\n" \
"\n\n connect " em(pInt) " to " em(pPulse) "\n" \
"\n\n raw MPU " \
" \n frequency count cycle "
long int oc=1, cntr=1;
unsigned long int tc=0;
void hwISR(){ cntr++; } // can count pulses if pInt <---> to pPulse
void anISR(){ tc=ESP.getCycleCount(); timer0_write( countFor + tc ); oc=cntr; cntr=1; }
void setup() { // need to still confirm duty cycle=50% (scope it or ...)
noInterrupts();
Serial.begin(115200); Serial.println(infoTxt); delay(10); // Serial.flush(); Serial.end(); // Serial timing?
analogWriteRange(qap); analogWriteFreq( HFreq ); analogWrite(pPulse, 1); // start PWM
pinMode( pInt, INPUT ); attachInterrupt(pInt, hwISR, RISING); // count pulses
timer0_isr_init(); timer0_attachInterrupt( anISR ); anISR(); //
interrupts();
}
void loop() { delay(10); if (oc==0) return;
Serial.println((String)" "+(oc/1000.0*F_CPU/countFor)+" KHz "+oc+" "+tc); oc=0; }
//

You can also use the hardware SPI interface which has an adjustable clock speed.
By writing continuous data, the output waveform appears on SCLK.
I've figured out the abovementioned while creating a knight rider effect with IC 74hc595 on ESP8266, using MicroPython (which is indeed slow, as being a script language).
It worked for me up to 4MHz SPI clock speed.
The disadvantage is, for permanent waveform, you need to write data to MOSI forever (as when SPI data buffer goes empty, there is no signal on SCLK anymore).

Related

TSL237 sensor on ESP8266 Wemos D1 Mini

I'm trying to read a TSL237 light sensor using my ESP8266 Wemos D1 Mini board. I have got code for an Arduino Uno from here (see copied below) and loaded it on my board. I first tried pin D0 on my board (GPIO 16) for the sensor data input, then pin D1 (GPIO5). In both cases I get the same useless output; I've copied one loop of this output below. Any ideas what I'm doing wrong?
CODE:
#define TSL237 2
volatile unsigned long pulse_cnt = 0;
void setup() {
attachInterrupt(0, add_pulse, RISING);
pinMode(TSL237, INPUT);
Serial.begin(9600);
}
void add_pulse(){
pulse_cnt++;
return;
}
unsigned long Frequency() {
pulse_cnt = 0;
delay(10000);// this delay controlls pulse_cnt read out. longer delay == higher number
// DO NOT change this delay; it will void calibration.
unsigned long frequency = pulse_cnt;
return (frequency);
pulse_cnt = 0;
}
void loop() {
unsigned long frequency = Frequency();
Serial.println(frequency);
delay(5000);
}
OUTPUT:
14:26:59.605 -> ets Jan 8 2013,rst cause:2, boot mode:(3,6)
14:26:59.605 ->
14:26:59.605 -> load 0x4010f000, len 3460, room 16
14:26:59.605 -> tail 4
14:26:59.605 -> chksum 0xcc
14:26:59.605 -> load 0x3fff20b8, len 40, room 4
14:26:59.605 -> tail 4
14:26:59.605 -> chksum 0xc9
14:26:59.605 -> csum 0xc9
14:26:59.605 -> v00041fe0
14:26:59.605 -> ~ld

ESP8266-12F WiFi soft AP config.authmode failed

For a project I try do use the ESP8266 RTOS SDK.
First step I install the tools and the toolchain. The hello_world example and the other gpio example works fine. I try the softAP example and get a Guru Meditation Error: Core 0 panic'ed (StoreProhibited). Exception was unhandled Error. I figured out that the line 62 : .automode = WIFI_AUTH_WPA_WPA2_PSK not works. I tried WIFI_AUTH_WEP,WIFI_AUTH_WPA_PSK,WIFI_AUTH_WPA2_PSK but only with WIFI_AUTH_OPEN the softAP works. Anyone same behavior or some tips?
Console Trace:
ets Jan 8 2013,rst cause:1, boot mode:(3,6)
load 0x40100000, len 7040, room 16
tail 0
chksum 0xe5
load 0x3ffe8408, len 24, room 8
tail 0
chksum 0x6c
load 0x3ffe8420, len 3312, room 8
tail 8
chksum 0x75
csum 0x75
I (123) boot: ESP-IDF v3.4-rc 2nd stage bootloader
I (123) boot: compile time 19:41:32
I (207) qio_mode: Enabling default flash chip QIO
I (207) boot: SPI Speed : 40MHz
I (208) boot: SPI Mode : QOUT
I (212) boot: SPI Flash Size : 2MB
I (219) boot: Partition Table:
I (224) boot: ## Label Usage Type ST Offset Length
I (236) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (247) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (259) boot: 2 factory factory app 00 00 00010000 000f0000
I (271) boot: End of partition table
I (277) esp_image: segment 0: paddr=0x00010010 vaddr=0x40210010 size=0x52c80 (339072) map
I (406) esp_image: segment 1: paddr=0x00062c98 vaddr=0x40262c90 size=0x0f594 ( 62868) map
I (428) esp_image: segment 2: paddr=0x00072234 vaddr=0x3ffe8000 size=0x005fc ( 1532) load
I (429) esp_image: segment 3: paddr=0x00072838 vaddr=0x40100000 size=0x00080 ( 128) load
I (439) esp_image: segment 4: paddr=0x000728c0 vaddr=0x40100080 size=0x05560 ( 21856) load
I (460) boot: Loaded app from partition at offset 0x10000
I (481) wifi softAP: ESP_WIFI_MODE_AP
I (484) system_api: Base MAC address is not set, read default base MAC address from EFUSE
I (486) system_api: Base MAC address is not set, read default base MAC address from EFUSE
phy_version: 1163.0, 665d56c, Jun 24 2020, 10:00:08, RTOS new
I (557) phy_init: phy ver: 1163_0
I (567) wifi softAP: ----------------###------------
ESP_ERROR_CHECK failed: esp_err_t 0x2 (ERROR) at 0x4021f7cc
file: "softap_example_main.c" line 73
func: wifi_init_softap
expression: esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config)
abort() was called at PC 0x4021f7cf on core 0
Guru Meditation Error: Core 0 panic'ed (StoreProhibited). Exception was unhandled.
Core 0 register dump:
PC : 0x40221c72 PS : 0x00000030 A0 : 0x40221c70 A1 : 0x3ffeb550
A2 : 0x00000000 A3 : 0xffffffdb A4 : 0x00000001 A5 : 0x00000001
A6 : 0x00000000 A7 : 0x4026663c A8 : 0x00000020 A9 : 0x00000000
A10 : 0x00000008 A11 : 0x00000000 A12 : 0x00000000 A13 : 0x00000000
A14 : 0x00000000 A15 : 0x00000000 SAR : 0x0000001e EXCCAUSE: 0x0000001d
Backtrace: 0x40221c72:0x3ffeb550 0x4021f7d2:0x3ffeb560 0x4022182e:0x3ffeb570 0x40221894:0x3ffeb630 0x402118ef:0x3ffeb640
Example Code from GitHub: (examples/wifi/getting_started/softAP/main/softap_example_main.c)
/* WiFi softAP Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "lwip/err.h"
#include "lwip/sys.h"
/* The examples use WiFi configuration that you can set via project configuration menu.
If you'd rather not, just change the below entries to strings with
the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
*/
#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID
#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD
#define EXAMPLE_MAX_STA_CONN CONFIG_ESP_MAX_STA_CONN
static const char *TAG = "wifi softAP";
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
if (event_id == WIFI_EVENT_AP_STACONNECTED) {
wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" join, AID=%d",
MAC2STR(event->mac), event->aid);
} else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d",
MAC2STR(event->mac), event->aid);
}
}
void wifi_init_softap()
{
tcpip_adapter_init();
ESP_ERROR_CHECK(esp_event_loop_create_default());
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL));
wifi_config_t wifi_config = {
.ap = {
.ssid = EXAMPLE_ESP_WIFI_SSID,
.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID),
.password = EXAMPLE_ESP_WIFI_PASS,
.max_connection = EXAMPLE_MAX_STA_CONN,
.authmode = WIFI_AUTH_WPA_WPA2_PSK
},
};
if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
}
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s",
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
}
void app_main()
{
ESP_ERROR_CHECK(nvs_flash_init());
ESP_LOGI(TAG, "ESP_WIFI_MODE_AP");
wifi_init_softap();
}
You have to run idf.py menuconfig and set the SSID and password values.
Password´s under 8 characters gets a Guru-Meditation ERR if the
wifi_config.ap.authmode = WIFI_AUTH_WEP or,
wifi_config.ap.authmode = WIFI_AUTH_WPA_PSK or,
wifi_config.ap.authmode = WIFI_AUTH_WPA2_PSK . Other authmodes not yet testet.
To provid this Error, make sure your pw has more then 7 characters or/and set
the If-Condition after the wifi_config to:
if (strlen(EXAMPLE_ESP_WIFI_PASS) < 8) {
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
ESP_LOGI(TAG," pw-lenght under 8 charcters. Set WIFI_AUTH_OPEN");
}
Your WiFi is not protectet but your µC not crashes.

Extract text from wrk output

I'm running a load test with wrk2 as a job on Jenkins. I'd like to send the results of the load test to Graylog but I only want to store the Requests/Sec and average latency.
Here's what the output looks like:
Running 30s test # https://example.com
1 threads and 100 connections
Thread calibration: mean lat.: 8338.285ms, rate sampling interval: 19202ms
Thread Stats Avg Stdev Max +/- Stdev
Latency 16.20s 6.17s 29.64s 65.74%
Req/Sec 5.00 0.00 5.00 100.00%
Latency Distribution (HdrHistogram - Recorded Latency)
50.000% 15.72s
75.000% 20.81s
90.000% 24.58s
99.000% 29.13s
99.900% 29.66s
99.990% 29.66s
99.999% 29.66s
100.000% 29.66s
Detailed Percentile spectrum:
Value Percentile TotalCount 1/(1-Percentile)
4497.407 0.000000 1 1.00
7561.215 0.100000 11 1.11
11100.159 0.200000 22 1.25
12582.911 0.300000 33 1.43
14565.375 0.400000 44 1.67
15720.447 0.500000 54 2.00
16416.767 0.550000 60 2.22
17301.503 0.600000 65 2.50
18464.767 0.650000 71 2.86
19185.663 0.700000 76 3.33
20807.679 0.750000 81 4.00
21479.423 0.775000 84 4.44
22347.775 0.800000 87 5.00
22527.999 0.825000 90 5.71
23216.127 0.850000 93 6.67
23478.271 0.875000 95 8.00
23805.951 0.887500 96 8.89
24723.455 0.900000 98 10.00
25067.519 0.912500 99 11.43
25395.199 0.925000 101 13.33
26525.695 0.937500 102 16.00
26525.695 0.943750 102 17.78
26705.919 0.950000 103 20.00
28065.791 0.956250 104 22.86
28065.791 0.962500 104 26.67
28377.087 0.968750 105 32.00
28377.087 0.971875 105 35.56
28475.391 0.975000 106 40.00
28475.391 0.978125 106 45.71
28475.391 0.981250 106 53.33
29130.751 0.984375 107 64.00
29130.751 0.985938 107 71.11
29130.751 0.987500 107 80.00
29130.751 0.989062 107 91.43
29130.751 0.990625 107 106.67
29655.039 0.992188 108 128.00
29655.039 1.000000 108 inf
#[Mean = 16199.756, StdDeviation = 6170.105]
#[Max = 29638.656, Total count = 108]
#[Buckets = 27, SubBuckets = 2048]
----------------------------------------------------------
130 requests in 30.02s, 13.44MB read
Socket errors: connect 0, read 0, write 0, timeout 1192
Requests/sec: 4.33
Transfer/sec: 458.47KB
Does anyone know how I could go about extracting Requests/sec (at the bottom) and the latency average to send as JSON parameters?
The expected output would be: "latency": 16.2, "requests_per_second": 4.33
You didn't provide the expected output so your question isn't clear but is this what you want?
$ awk 'BEGIN{a["Latency"]; a["Requests/sec:"]} ($1 in a) && ($2 ~ /[0-9]/){print $1, $2}' file
Latency 16.20s
Requests/sec: 4.33
Updated based on you adding expected output to your question:
$ awk '
BEGIN { map["Latency"]="latency"; map["Requests/sec:"]="requests_per_second" }
($1 in map) && ($2 ~ /[0-9]/) { printf "%s\"%s\": %s", ofs, map[$1], $2+0; ofs=", " }
END { print "" }
' file
"latency": 16.2, "requests_per_second": 4.33

How to get images from raster bands using OpenCV?

I have different raster bands and I need to get a proper image from these bands using OpenCV. How can it be done?
As an alternative to my other answer, you could put a small ASCII header on your raw files to make them into PGM files which OpenCV can read natively without any extra libraries. The PGM format is part of the NetPBM suite described here on Wikipedia.
So, let's say each of your rasters is a single channel, 8-bit image with dimensions 100 px wide by 256 px tall. Make each band into a PGM image in the Terminal:
{ printf "P5\n100 256\n255\n"; cat band1.dat; } > band1.pgm
{ printf "P5\n100 256\n255\n"; cat band2.dat; } > band2.pgm
{ printf "P5\n100 256\n255\n"; cat band3.dat; } > band3.pgm
{ printf "P5\n100 256\n255\n"; cat band4.dat; } > band4.pgm
You now have 4 greyscale images you can view with GIMP or feh and, more importantly which OpenCV can read. So your code becomes:
Mat b1 = imread("band1.pgm", IMREAD_UNCHANGED);
Mat b2 = imread("band2.pgm", IMREAD_UNCHANGED);
Mat b3 = imread("band3.pgm", IMREAD_UNCHANGED);
Mat b4 = imread("band4.pgm", IMREAD_UNCHANGED);
// Now merge
auto channels = std::vector<cv::Mat>{b1, b2, b3, b4};
cv::Mat FourBandBoy;
cv::merge(channels, FourBandBoy);
As you haven't provided any sample raster images, I made 4 images, each 100x256, for a quick demonstration. Here they are:
-rw-r--r-- 1 mark staff 25600 21 Mar 10:44 band1.dat
-rw-r--r-- 1 mark staff 25600 21 Mar 10:44 band2.dat
-rw-r--r-- 1 mark staff 25600 21 Mar 10:44 band3.dat
-rw-r--r-- 1 mark staff 25600 21 Mar 10:44 band4.dat
Hopefully, you can see from the sizes that they are 100x256, single channel and 8-bit.
I the converted them to PGM per the original instructions:
{ printf "P5\n100 256\n255\n"; cat band1.dat; } > band1.pgm
{ printf "P5\n100 256\n255\n"; cat band2.dat; } > band2.pgm
{ printf "P5\n100 256\n255\n"; cat band3.dat; } > band3.pgm
{ printf "P5\n100 256\n255\n"; cat band4.dat; } > band4.pgm
which gives:
-rw-r--r-- 1 mark staff 25615 21 Mar 10:44 band1.pgm
-rw-r--r-- 1 mark staff 25615 21 Mar 10:44 band2.pgm
-rw-r--r-- 1 mark staff 25615 21 Mar 10:44 band3.pgm
-rw-r--r-- 1 mark staff 25615 21 Mar 10:44 band4.pgm
So, you can see the PGM header amounts to 15 bytes. The images look like this now:
I slightly modified the code:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <cstdio>
using namespace cv;
using namespace std;
int
main(int argc,char*argv[])
{
Mat b1 = imread("band1.pgm", IMREAD_UNCHANGED);
Mat b2 = imread("band2.pgm", IMREAD_UNCHANGED);
Mat b3 = imread("band3.pgm", IMREAD_UNCHANGED);
Mat b4 = imread("band4.pgm", IMREAD_UNCHANGED);
// Now merge
auto channels = std::vector<cv::Mat>{b1,b2,b3,b4};
cv::Mat BigBoy;
cv::merge(channels, BigBoy);
// Save
cv::imwrite("result.png",BigBoy);
}
And the result...
Hopefully you can see that the resulting image:
is blue where there was a lot of white in band1,
is green where there was a lot of white in band2,
is red where band3 was white
is transparent where band 4 was black
I don't feel like writing all the code and testing it like I ordinarily might so I'll just give you an outline of one way to do it.
Assume your images are WIDTHxHEIGHT in dimension and made of unsigned char data written consecutively without padding into files called band1.dat, band2.dat etc.
// Step 1: Allocate a buffer: raw = WIDTHxHEIGHT bytes
// Step 2: Load one band from disk into raw buffer
open band1.dat, read WIDTH*HEIGHT bytes into raw, close band1.dat
// Make a single band Mat from that data
cv::Mat band1(HEIGHT,WIDTH,CV_8UC1);
// Copy the raw data into it so we can re-use buffer
std::memcpy(band1.data,raw,WIDTH*HEIGHT);
// Repeat step 2 for bands 2-4 so you have 4 separate, single channel Mats
// Now merge the 4 individual channels into 4-band bad boy
auto channels = std::vector<cv::Mat>{band1, band2, band3, band4};
cv::Mat FourBandBoy;
cv::merge(channels, FourBandBoy);

iOS 64bit ntpdate don't work properly with arm64 flag

I have a function (ANSI C) to retrieve time for our ntpd server.
This code work properly when I compile 32bit but doesn't work if I compile in armv64.
It works properly on iPhone 4,4S,5 (32bit), it doesn't work properly on Iphone 5s,6,6S (64bit).
I think that the problem is:
tmit=ntohl((time_t)buf[10]); //# get transmit time
time_t is now 8byte when compiled in armv64.....
Underneath you can find the source code...
Output Correct with Iphone 5 Simulator (32bit) ---------------------------
xxx.xxx.xxx.xxx PORT 123
sendto-->48
prima recv
recv-->48
tmit=-661900093
tmit=1424078403
1424078403-->Time: Mon Feb 16 10:20:03 2015
10:20:03 --> 37203
---------------------------------------------------------
Output Wrong with Iphone 6 Simulator (64bit) ---------------------------
xxx.xxx.xxx.xxx PORT 123
sendto-->48
prima recv
recv-->48
tmit=19612797
tmit=2105591293
2105591293-->Time: Tue Nov 19 00:47:09 38239
00:47:09 --> 2829
//---------------------------------------------------------------------------
long ntpdate(char *hostname) {
//ntp1.inrim.it (193.204.114.232)
//ntp2.inrim.it (193.204.114.233)
int portno=NTP_PORT; //NTP is port 123
int maxlen=1024; //check our buffers
int i=0; // misc var i
unsigned char msg[48]={010,0,0,0,0,0,0,0,0}; // the packet we send
unsigned long buf[maxlen]; // the buffer we get back
//struct in_addr ipaddr; //
struct protoent *proto; //
struct sockaddr_in server_addr;
int s; // socket
int tmit; // the time -- This is a time_t sort of
char ora[20]="";
//
//#we use the system call to open a UDP socket
//socket(SOCKET, PF_INET, SOCK_DGRAM, getprotobyname("udp")) or die "socket: $!";
proto=getprotobyname("udp");
s=socket(PF_INET, SOCK_DGRAM, proto->p_proto);
if(s==-1) {
//printf("ERROR socket=%d\n",s);
return -1;
}
//Setto il timeout per la ricezione --------------------
struct timeval tv;
tv.tv_sec = TIMEOUT_NTP; //sec
tv.tv_usec = 0;
if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval)) != 0)
{
//printf("Error assigning socket option");
return -1;
}
memset( &server_addr, 0, sizeof( server_addr ));
server_addr.sin_family=AF_INET;
//trasformo il nome in ip
struct hostent *hp = gethostbyname(hostname);
if (hp == NULL) {
return -1;
} else {
sprintf(hostname_ip, "%s", inet_ntoa( *( struct in_addr*)( hp -> h_addr_list[0])));
}
#ifdef LOG_NTP
printf("%s-->%s PORT %d\n",hostname,hostname_ip,portno);
#endif
server_addr.sin_addr.s_addr = inet_addr(hostname_ip);
server_addr.sin_port=htons(portno);
//printf("ipaddr (in hex): %x\n",server_addr.sin_addr);
/*
* build a message. Our message is all zeros except for a one in the
* protocol version field
* msg[] in binary is 00 001 000 00000000
* it should be a total of 48 bytes long
*/
// send the data
i=sendto(s,msg,sizeof(msg),0,(struct sockaddr *)&server_addr,sizeof(server_addr));
#ifdef LOG_NTP
printf("sendto-->%d\n",i);
#endif
if (i==-1)
return -1;
#ifdef LOG_NTP
printf("prima recv\n");
#endif
// get the data back
i=recv(s,buf,sizeof(buf),0);
#ifdef LOG_NTP
printf("recv-->%d\n",i);
#endif
if (i==-1)
{
#ifdef LOG_NTP
printf("Error: %s (%d)\n", strerror(errno), errno);
#endif
return -1;
}
//printf("recvfr: %d\n",i);
//We get 12 long words back in Network order
//for(i=0;i<12;i++)
//printf("%d\t%-8x\n",i,ntohl(buf[i]));
/*
* The high word of transmit time is the 10th word we get back
* tmit is the time in seconds not accounting for network delays which
* should be way less than a second if this is a local NTP server
*/
tmit=ntohl((time_t)buf[10]); //# get transmit time
#ifdef LOG_NTP
printf("tmit=%d\n",tmit);
#endif
/*
* Convert time to unix standard time NTP is number of seconds since 0000
* UT on 1 January 1900 unix time is seconds since 0000 UT on 1 January
* 1970 There has been a trend to add a 2 leap seconds every 3 years.
* Leap seconds are only an issue the last second of the month in June and
* December if you don't try to set the clock then it can be ignored but
* this is importaint to people who coordinate times with GPS clock sources.
*/
tmit-= 2208988800U;
#ifdef LOG_NTP
printf("tmit=%d\n",tmit);
#endif
/* use unix library function to show me the local time (it takes care
* of timezone issues for both north and south of the equator and places
* that do Summer time/ Daylight savings time.
*/
//#compare to system time
#ifdef LOG_NTP
//printf("%d-->Time: %s\n",tmit,ctime((const time_t)&tmit));
printf("%d-->Time: %s\n",tmit,ctime((const time_t)&tmit));
#endif
//i=time(0);
//printf("%d-%d=%d\n",i,tmit,i-tmit);
//printf("System time is %d seconds off\n",i-tmit);
//Prendo l'ora e la converto in HH:MM:SS --> Sec
strftime(ora, 20, "%T", localtime((const time_t)&tmit));
#ifdef LOG_NTP
printf("%s --> %ld\n",ora, C2TIME(ora));
#endif
return C2TIME(ora);
}
I Solved the Problem!!!!!!!!!
uint32_t buf[maxlen];
uint32_t tmit;
instead of:
unsigned long buf[maxlen];
int tmit;
Defining a variable of type time_t
time_t tmit_temp=tmit;
printf("%d-->Time: %s\n",tmit,ctime((const time_t)&tmit_temp));
strftime(ora, 20, "%T", localtime((const time_t)&tmit_temp));
This works properly!!! ;-)

Resources