2017年6月20日 星期二

[C#]Array.Join

最近遇到一個需求,把1234 ---> 1,2,3,4

所以用到String.Join這個方法

public static string Join(
 string separator,
 params string[] value
)

第一個參數separator是表示你要用什麼分隔符號,例如,。

第二個參數則是要合併的String Array 


使用範例如下,輸出為1,2,3,4



String source="1234";
char[] charArray=source.ToCharArray();
String dist=String.Join(",",charArray);
Console.WriteLine(dist);

參考網頁:

https://msdn.microsoft.com/zh-tw/library/57a79xd0(v=vs.110).aspx

2017年6月19日 星期一

「電路」第一次焊SMD

上次去上IoT Sensor hand on 1 時買了一塊NodeMCU半成品板


只要把ESP8266 12E焊上去就可以了。


先用絕綠耐熱膠帶固定一下


焊好後,先用3用電錶量一下,確定沒有短路再上電


2017年6月8日 星期四

[Arduino]NTSC 4K7 量測溫度方法.

最近遇到一個溫度計,它只有2條線,Orz ,看起來不可能是1-Wire,

研究了一下發現是電阻式的溫度計,也就是熱敏電阻。

在25度西時大約是4.77K歐姆,在30度西時是38.8K歐姆,代表溫度上升阻值下降,

所以不可能是有名的PT100(0度西時阻值為100歐姆),去查了一下類似的數據,



接下來是該如何得到阻值變化 ----> 串聯一個固定阻值的電阻,就可以依電壓

變化的比例,知道目前溫度計的阻值,上面的4.7K表示溫度計的阻值,

下面量測的部份則是固定阻值的4.7K電阻。


2017年6月7日 星期三

[Arduino] I2C Scann

最近使用DAC時,看了很多文件和範例,都沒有反應,原因是I2C Address錯了,

當你使用I2C時,其實有一個方法可以掃描出正確的I2C Address

// --------------------------------------
// i2c_scanner
//
// Version 1
//    This program (or code that looks like it)
//    can be found in many places.
//    For example on the Arduino.cc forum.
//    The original author is not know.
// Version 2, Juni 2012, Using Arduino 1.0.1
//     Adapted to be as simple as possible by Arduino.cc user Krodal
// Version 3, Feb 26  2013
//    V3 by louarnold
// Version 4, March 3, 2013, Using Arduino 1.0.3
//    by Arduino.cc user Krodal.
//    Changes by louarnold removed.
//    Scanning addresses changed from 0...127 to 1...119,
//    according to the i2c scanner by Nick Gammon
//    http://www.gammon.com.au/forum/?id=10896
// Version 5, March 28, 2013
//    As version 4, but address scans now to 127.
//    A sensor seems to use address 120.
// Version 6, November 27, 2015.
//    Added waiting for the Leonardo serial communication.
//
//
// This sketch tests the standard 7-bit addresses
// Devices with higher bit address might not be seen properly.
//
 
#include <Wire.h>
 
 
void setup()
{
  Wire.begin();
 
  Serial.begin(9600);
  while (!Serial);             // Leonardo: wait for serial monitor
  Serial.println("\nI2C Scanner");
}
 
 
void loop()
{
  byte error, address;
  int nDevices;
 
  Serial.println("Scanning...");
 
  nDevices = 0;
  for(address = 1; address < 127; address++ )
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
 
    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");
 
      nDevices++;
    }
    else if (error==4)
    {
      Serial.print("Unknown error at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");
 
  delay(5000);           // wait 5 seconds for next scan
}

資料來源:

https://playground.arduino.cc/Main/I2cScanner

[Arduino] millis() 使用注意事項

最近在在Arduino上每隔五分鐘要用MQTT傳一次資料給SERVER,所以

millis() 這個函式來取得arduino執行程式到目前過了幾個milliseconds 

但這個值是用unsign long (32bit) 儲存的,所以大概在約50天左右就會overflow,

從0開始,但是如果程式寫法是如下,那就好笑了。


unsigned long start=millis();
int delaytime=3000;
void loop() {
  

while (millis()<start+delaytime)
{
    ;
}
sendData();

}


當五十天後,你就永遠不會傳送資料了,因為millis()可能會遠小於sendtime。等到大於sendtime時,差不多又overflow了。

但是以下的寫法是不會有問題的


unsigned long start=millis();
unsigned long delay=3000;
if (millis()-start>delay)
{
    sendData();
    start=millis();
}

我們先來了解一下unsigned long 到底可以放的下什麼

0 to 4,294,967,295 (2^32 - 1)


那如果overflow 後會發生什麼事

unsigned long number=4294967295;  
void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);


  Serial.println("number is :"+String(number));
  number+=1;
  Serial.println("number+1 is :"+String(number));
}


輸出結果如下,當大於2^32 -1 後,就會歸零。

number is :4294967295
number is :0

我們來模擬一下overflow之後的運算


unsigned long number=4294967295; 
unsigned long testNumber=4294967295; 
void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);


  Serial.println("number is :"+String(number));
  number+=1;
  Serial.println("number+1 is :"+String(number));
  Serial.println("number- 2^32-1 :"+String(number-testNumber));

}

number is :4294967295
number+1 is :0
number- 2^32-1 :1

所以0-(2^32-1) 會是1  ,

以此類推,當overflow後,即使millis()比較小,相滅之後仍然會是正值。

number is :4294967295
number+10000 is :9999
number- 2^32-1 :10000

我們來測試一下,若是millis()比較小時做相減會怎樣

number is :0
number+10000 is :10000
number- 2^32-1 :10001

所以2數運算時要考慮到unsigned long 能裝的下的空間,unsigned long 面對運算結果負值也會出現問題。

number is :0
number+10000 is :10000
number-10001 :4294967295



參考資料:

millis() 溢出(overflow)歸零(rollover)有沒問題?(教程)定时器相關http://www.arduino.cn/thread-12506-1-1.html

「Arduino」MQTT踩到一個坑

紀錄一下使用MQTT時採到的一個坑,在爬回平地前先來

看看Pubsubclient lib裡面一個基本的範例 ,不可否認的,這範例寫的很清楚。

我的MQTT Broker是mosquitto 1.4.x 版


#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>

// Update these with values suitable for your network.
byte mac[]    = {  0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
IPAddress ip(172, 16, 0, 100);
IPAddress server(172, 16, 0, 2);

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i=0;i<length;i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

EthernetClient ethClient;
PubSubClient client(ethClient);

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("arduinoClient")) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("outTopic","hello world");
      // ... and resubscribe
      client.subscribe("inTopic");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup()
{
  Serial.begin(57600);

  client.setServer(server, 1883);
  client.setCallback(callback);

  Ethernet.begin(mac, ip);
  // Allow the hardware to sort itself out
  delay(1500);
}

void loop()
{
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
}

單一台裝置運作時,非常順利,但是同樣的程式碼,在二個arduino上執行時會出現

漏訊息,而且拼命和MQTT Broker Reconnect問題。

查詢了一下錯誤代碼,rc=-4表示 Connection Timeout , 在MQTT中,client與server之間會

有一個keepalive的參數,這個lib預設是15秒,也就是在15內,client有義務和server保持連

接,當超過keepalive所設定的秒數內沒有傳送資料,client必須發送一個心跳訊號,而server

在收到心跳訊號後,必須回覆,這個client才能確認與server是保持連通的。


後來確認後發現是這一行程式碼導致的問題

if (client.connect("arduinoClient"))

一眼瞄過去我也不覺得那裡有異,直到去查詢後才發現"arduinoClient" 其實是

ClientID  , 所以不應該重覆,否則Server會無法正確識別與client連線狀態,導致Client

可能沒有正確收到Server response 的keepalive回覆,誤以為斷線。

「Android」Samsung S8 省電模式Ping指令異常

最近客戶反應S8不能正常使用我們家的APP,測了一整天都找不出問題,

最後把省電模式開啟動,出現問題。

最後確認是,當S8開啟省電模式時,PING 會沒有正確回應,導致程式判斷

網路是否順暢時出現錯誤回應。


但是若是使用HTTP連線一個IP位址,則是正常的。

EX: Ping 8.8.8.8   在省電模式開啟時,將得不到正常的回應(網頁可正常開啟)。
































而省電模式關閉後,Ping 8.8.8.8 則可以得到GOOGLE DNS如下回應。

64 bytes from 8.8.8.8: icmp_seq=0 ttl=43 time=50.361 ms
64 bytes from 8.8.8.8: icmp_seq=1 ttl=43 time=18.438 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=43 time=19.047 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=43 time=51.853 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=43 time=18.523 ms
64 bytes from 8.8.8.8: icmp_seq=5 ttl=43 time=17.286 ms

64 bytes from 8.8.8.8: icmp_seq=6 ttl=43 time=17.853 ms