2017年12月18日 星期一

「iOS」[Firebase] iOS存取Firebase Realtime Database(1)

紀錄一下自己用iOS來存取Firebase Realtime Database

首先到進入到Firebase
https://console.firebase.google.com/u/2/

















新增專案



















點選iOS











先開啟xcode,建立一個iOS專案














重點在於紅框框中那一行,先記下等等有妙用














按下Next把專案建立好,再來回到Firebase



















把剛才記下的 Bundle Identifier填入,註冊應用程式
















下載GoogleService-Info.plist並放到專案目錄下



















接下來會用到CocoaPods ,如果沒安裝過,請先安裝,

不知道cocoaPods是什麼可以參考這一篇 , 安裝只需要在終端機輸入

sudo gem install cocoapods


接下來要進到專案根目錄下,開啟終端機並進入專案目錄

cd iOSDemo

初始化cocoaPods

pod init

此時目錄下會出現Podfile ,表示初始化cocoaPods成功






編輯Podfile 

vi Podfile

並在# Pods for iOSDemo下方加入二行

pod 'Firebase/Core'
pod 'Firebase/Database'





















存檔後,先裝Xcode關掉(很重要)

輸入下列指令開始安裝插件

pod install














接下來在輸入以下指令,開啟剛剛的專案

open iOSDemo.xcworkspace

此時會發現專案中多了一個Pods表示Firebase SDK安裝成功囉~


接下來是初始化Firebase ,打開AppDelegate.swift

import Firebase

並在
func application(_ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions

中加入

FirebaseApp.configure()

先Build一次看看,如果編譯成功,可以開啟模擬器執行,會有Firebase Log輸出。

下一篇會介紹如何新增,修改,刪除,讀取




2017年12月16日 星期六

[名詞定義][iOS]COCOAPODS

CocoaPods,它是一種支援 Swift 和 Objective-C 程式開發的

第三方庫資源相依性管理工具。



例如iOS APP使用如Firebase SDK , ,所以需要滙入包括Firebase本身及所需相關的類別

庫。開發者如果手動去處理,是一個很麻煩且易出錯的過程,日後如果Firebase SDK 或相關

的類別庫有更新時,就必須手動一個一個處理,且容易遇到版本相依性問題。

為了方便管理類別庫,因而𧗠生不少相依性管理工具 ,透過此工具解決開發者必須手動處理

類別庫更新問題。

OS X安裝方式

sudo gem install cocoapods


















安裝會需要一點點時間,東西有點多。

之後使用方式則如下,進入到專案根目錄

cd myiOSProgram

初始化cocoappods

vi Podfile

在檔案中加入所需要的類別庫,例如firebase



接下來安裝相關類別庫

pod install

參考來源:

https://www.appcoda.com.tw/cocoapods/


2017年11月18日 星期六

「分享」智慧存錢筒機器人

在網路上看到一個很可愛的課程。


























200 大洋含課程與材料,做完可以帶走,直接就繳費了,到了現場,

有做好的展示品,先拍一張,好可愛。

























材料,我用鼻子聞了一下,紙板是用雷雕機切割的焦味...


唯一的電子零件,馬達,3V,25 RPM



















































開始用熱融膠黏紙板





















最後組裝結果












































































主要的運作原始是當銅板放上去後,會使拖盤上的二個迴紋針導通,

驅動馬達轉動,使馬達上的迴紋針頂住頭部,打開嘴巴,因頭部與手臂

間是以吊魚線拉住,所以手也會一併抬起使錢掉進嘴巴中,接下來因抬頭,

使後背後的鋁泊貼紙與背上的迴紋針導通,又驅動馬達轉送,不再頂住頭部,

回復正常狀態。


2017年10月18日 星期三

[MCU]PIC18F45K20 Demo board LED Example

手邊有一組 PICkit 44-Pin Demo Board (PIC18F45K20)


這塊版子的LED在RD0~RD7

可變電阻(右上方)接在RA0

Switch Button(右下方)接在RB0

程式碼如下
#pragma config FOSC = INTIO67    // FOSC = INTIO67 Internal oscillator block
#pragma config WDTEN = OFF, LVP = OFF    // LVP = OFF Single-Supply ICSP disabled
                                         //WDTEN = OFF Watch dog timer is always disabled. SWDTEN has no effect.
 #include "p18f45k20.h"   //inclue this mcu header
 
 void delay();   
 //delay function   
 void delay() {      
    int counter = 0;   
    for (counter = 0; counter<1000; counter++);    
 }   
 void main(void) {      
    int dummy = 0;   
    /*init the RA0 as analog input*/   
    TRISA = 0x1; // set potentiometer at porta as input (only set port A0)    
    ANSELbits.ANS0 = 1; // set RA0 to analog (=1, 0 = digital) -> this is important to potentiometer  at RA0      
    ADCON0bits.ADON = 1; // activate A/D unit   
    /*init the RB0 as digital input*/   
    TRISB = 0x1; // set bit0 of portb to input because there is the push button at RB0      
    ANSELHbits.ANS12 = 0; // set RB0 to digital (=0, 1= analog) -> this is important to read button at RB0   
    /*init the RD0..RD7(PORTD) as digital output*/   
    TRISD = 0; // all bits of portd are set 0 as output      
    PORTD = 0; // deactivate all led's   
                                                                                                                                                                 
    while (1) {          
       if (PORTBbits.RB0 == 0) { //check if button is pressed (=0, 1= not pressed)                          
          ADCON0bits.GO_DONE = 1; // start A/D convert              
          while(ADCON0bits.GO_DONE != 0); // wait till A/D convert done               
          dummy = ADRESH; // copy A/D result (high part) to leds -> dummy variable is only for better debugging              
          PORTD = dummy;          
       } else {              
          PORTD = PORTD<<1; // move set led   
          if (PORTD == 0) {    
             PORTD = 0x1; // if all led's off activate one   
          }          
       }   
       delay();      
    }       
 }   
 



程式碼內容主要為

config
設定使用內建震盪器、關閉看門狗

pin define

設定RA0為類比輸入
RB0為類比輸入
RD0~7為輸出

function
若switch button沒有按下,則執行跑馬燈,

若按下則讀取RA0的類比輸入並透過LED
顯示數值。












一開始遇到的困難是程式build success,按燒錄後卻沒有任何反應,

以下有二個小心得:

(1) 燒錄時Pickit 3要供電3.25V
(2)必須按下Run Project,單獨program的話,只會在燒錄過程中供電,燒完就沒電了,
當然不會亮囉。

晚安囉~

參考資料:

2017年10月16日 星期一

[iOS] Signing for "Map" requires a development team.


初用MapKit,編譯時遇到這個錯誤

Signing for "Map" requires a development team.


解法如下:

1.登入APPLE ID


2.在Signing設定Team即可(我的APPLE ID是沒有交99鎂的)

3.重新Builder



2017年10月14日 星期六

「電路」邏輯電平轉換

當你有3.3V 和5V需要UART通訊的需求時,會需要一個電平轉換IC,不然3.3V那邊可能

會燒毀。


我用的是這一顆 3.3V 5V Logic Level Converter



購買網址如下:
https://ok.100y.com.tw/Goods/97459


LV接3.3V , HV接5V,接下來就可以進行UART的通訊,實際測過7688與Arduino nano

是OK的,可以正常通訊。

[C] fget read stdin after scanf("%d"...) not work

最近遇到一個問題,當我用fget讀取訊息後,並沒有進行讀取,程式碼如下



#include <stdio.h>
#include <string.h>


int main(void)
{


char message[200];
int ID;




printf("\t[Info] 請輸入員工編號:");
scanf("%d", &ID);


printf("員工編號:%d",ID);

printf("\n 請輸入要傳遞老闆的訊息:" );
fgets(message,sizeof(message),stdin);

printf("您傳給老闆的訊息:%s",message);

}

執行結果:




網路上查詢後,發現問題如下:

When you read the integer with scanf("%d"....), it does not remove the newline from the input stream. So when you call fgets later, it reads and finds a newline , i.e. you read a blank line.
To read the next line instead you will need to consume that newline, e.g. getchar() as someone else suggested.

因為scanf("%d,...")並不讀進換行字元,當您在之後使用fget時,

就會直接讀到一個換行字元,然候就結束了,所以必須先處理掉這個換行字元,

透過getchar()這個method去讀一個字元。

修正後的程式碼如下:

#include <stdio.h>
#include <string.h>


int main(void)
{


char message[200];
int ID;




printf("\t[Info] 請輸入員工編號:");
scanf("%d", &ID);


printf("員工編號:%d",ID);

getchar();

printf("\n 請輸入要傳遞老闆的訊息:" );
fgets(message,sizeof(message),stdin);

printf("您傳給老闆的訊息:%s",message);

}

執行結果:




參考來源:
https://stackoverflow.com/questions/22552166/fgets-not-working-in-c-linux

2017年10月10日 星期二

[分享]碟剎油(剎車油)更換

某一天和朋友出去,友人突然發現我的剎車油變黑了,建議快去換。

以下是後碟剎油,里程數約8K



前碟剎油



明顯發現後碟剎劣化快多了。

更換前後剎車油600(前250,後350),記得要找信任的店家,

剎車油更換中如果有空氣進入管道中,剎車壓力會不見(也就是失靈),

更換完畢後,必須要用清潔濟清洗週邊,剎車油具有腐蝕性,會吃漆,

弄壞你的外殻,千萬不要滴到。

最後來一張,更換後的。


其實我可以只換後碟剎油的,但想說前碟雖然沒有劣化那麼嚴重,

就一起換一換吧,老闆說一般即使黑掉還是能使用,只要別拖到

開始結塊了,一般來說每1萬二千公里要檢查一次。

「單字筆記」 Insurance claims

Insurance claims   保險理賠
[ in'ʃuərəns ] [kl'em] 

「單字筆記」mandatory

mandatory  「ˈmandəˌtôrē

adj.強制的;命令的;受委託的;

n.受托者;

Mandatory sign: mandatory sign requires specific behaviors or action.
強制性標識:強制性標識是對行為或行動的明確要求。

It is mandatory to rate overall achievement of specific objectives and general performance via this scale.
通過這種尺度對所有特殊的宗旨和一般的業績是強制性的。


資料來源:
https://tw.voicetube.com/definition/mandatory

「分享」用地址查詢地號

有時候需要去查詢地政資料時,會需要你家的地號和建號,讓如何查詢呢?

有一個免費的系統

地籍圖資網路便民服務系統:
http://easymap.land.moi.gov.tw/R02/Index

我們來查一下高雄市政府四維行政中心的地號吧

802高雄市苓雅區四維三路2號



















按下查詢後



















放大一點看看


























有了這些,你就可以申請到地政膽本。

2017年10月9日 星期一

[arduino] Arduino Nano 使用DFRobot LCD KeyPad Shield

首先介紹一下二個主角

  1. Arduino Nano
    1. 官方的說明 -->The Arduino Nano is a compact board similar to the UNO. (Arduino Nano是一塊類似於UNO的簡潔版)
      它的體型比較小,而且Analog Input有8支,比UNO多二支。

      資料及圖片來源:
      https://store.arduino.cc/usa/arduino-nano
  2. DFRobot LCD KeyPad Shield
    1. 這是一塊For UNO的擴充版,上面有一個1602LCD及幾個按鈕。
    2. 使用到的PIN如下表
      Analog 0是透過不同按鈕會輸出不同的電壓來分辨是那一個按鈕
       if (adc_key_in < 50)   return btnRIGHT;  
       if (adc_key_in < 250)  return btnUP; 
       if (adc_key_in < 450)  return btnDOWN; 
       if (adc_key_in < 650)  return btnLEFT; 
       if (adc_key_in < 850)  return btnSELECT;  
      Analog 0Button (select, up, right, down and left)
      Digital 4DB4
      Digital 5DB5
      Digital 6DB6
      Digital 7DB7
      Digital 8RS (Data or Signal Display Selection)
      Digital 9Enable
      Digital 10Backlit Control
              我們依照以上接腳定義,將其接上nano的D4~D10即可使用1602LCD的功能。

2017年9月30日 星期六

[Arduino]MCP4728 修改I2C Address

MCP4728簡介如下:
Features
• 12-Bit Voltage Output DAC with Four Buffered Outputs
• On-Board Nonvolatile Memory (EEPROM) for DAC Codes and I2C™ Address Bits
• Internal or External Voltage Reference Selection
• Output Voltage Range:
- Using Internal VREF (2.048V):
0.000V to 2.048V with Gain Setting = 1
0.000V to 4.096V with Gain Setting = 2
- Using External VREF (VDD):
0.000V to VDD • ±0.2 Least Significant Bit (LSB) Differential Nonlinearity (DNL) (typical)
• Fast Settling Time: 6 µs (typical)
• Normal or Power-Down Mode
• Low Power Consumption
• Single-Supply Operation: 2.7V to 5.5V
• I2C Interface: - Address bits: User Programmable to EEPROM
- Standard (100 kbps), Fast (400 kbps) and High Speed (HS) Mode (3.4 Mbps) • 10-Lead MSOP Package • Extended Temperature Range: -40°C to +125°C

資料來源:
http://ww1.microchip.com/downloads/en/DeviceDoc/22187E.pdf

它是一顆擁有四個類比輸出的DAC,透過I2C介面做控制。

12Bit 解析度,可以把輸出的電壓分成4096等份,例如輸出0~5V, 則可以將電壓的精準度

達到 0.001

可有以下幾種模式(透過指令即可變更):

使用外部參考電壓,例如5V 。

使用內部參考電壓  Gain =1
0.000V to 2.048V

使用內部參考電壓 Gain  =2
0.000V to 4.096V

如果要求精準,建議使用內部參考電壓 Gain =1  ,並透過穩壓IC供電給DAC。

如果要使用多組DAC在電路中,則需要改變MCP4728的I2C位置,我們先來看一下

datasheet中的說明


MCP4728預設的I2C位置為0x61 , 也就是1100001 ,也就是A2=0 , A1=0 ,A0=1

如果今天我要把它改成0x60 (1100000), New Address bit A2=0, A1=0 , A0=0 。 

把現有的位置和新的位置依照上面填空後,就是4個byte的指令,接下來要接上

LDAC這支Pin腳,它需要在第2個byte傳送到第8個bit時,將LDAC由HIGH轉LOW,

否則怎麼傳送指令都會失敗,注意必須在MCP4728回傳ACK 之前就要轉LOW,

所以用Arduino內建的Wire.Write會失敗,弄了2天,請教了Firmware朋友,得到的

答案建議自己去控制I2C通訊時的HIGH ,LOW ,才能在第八個bit時將LDAC轉LOW,

等到ACK回來就來不了。來看一下接線

Arduino UNO                MCP4728
VCC                             VDD
GND                             VSS
2                                 SCL
3                                 SDA
8                                  LDAC






















接下來是我去網路上找的一份程式碼,整理之後,確認可以成功。
將預設的0x61位置改成0x60


// R/W direction bit to OR with address for start or restart
#define I2C_READ 1
#define I2C_WRITE 0
#define SOFT_I2C_MASTER
#define I2C_DELAY_USEC 10
#define ldac_pin 8

uint8_t sclPin_;
uint8_t sdaPin_;

unsigned char OldAddr = 0x1;  //0x61 default I2C Address
unsigned char NewAddr = 0x0;  //0x60 new I2C Address

//I2C Init
void init(uint8_t sclPin, uint8_t sdaPin)
{
  sclPin_ = sclPin;
  sdaPin_ = sdaPin;
  pinMode(sclPin_, OUTPUT);
  digitalWrite(sdaPin_, HIGH); //Mark_H fix
  pinMode(sdaPin_, OUTPUT);
  digitalWrite(sclPin_, HIGH);
  digitalWrite(sdaPin_, HIGH);
}
//------------------------------------------------------------------------------
// read a byte and send Ack if last is false else Nak to terminate read
uint8_t read(uint8_t last)
{
  uint8_t b = 0;
  // make sure pullup enabled
  digitalWrite(sdaPin_, HIGH);
  pinMode(sdaPin_, INPUT);
  // read byte
  for (uint8_t i = 0; i < 8; i++) {
    // don't change this loop unless you verify the change with a scope
    b <<= 1;
    delayMicroseconds(I2C_DELAY_USEC);
    digitalWrite(sclPin_, HIGH);
    if (digitalRead(sdaPin_)) b |= 1;
    digitalWrite(sclPin_, LOW);
  }
  // send Ack or Nak
  digitalWrite(sdaPin_, HIGH); 
  pinMode(sdaPin_, OUTPUT);
  digitalWrite(sdaPin_, last);
  digitalWrite(sclPin_, HIGH);
  delayMicroseconds(I2C_DELAY_USEC);
  digitalWrite(sclPin_, LOW);
  digitalWrite(sdaPin_, HIGH);
  return b;
}
//------------------------------------------------------------------------------
// send new address and read/write without stop
uint8_t restart(uint8_t addressRW)
{
  digitalWrite(sclPin_, HIGH);
  return start(addressRW);
}
//------------------------------------------------------------------------------
// issue a start condition for i2c address with read/write bit
uint8_t start(uint8_t addressRW)
{
  digitalWrite(sdaPin_, LOW);
  delayMicroseconds(I2C_DELAY_USEC);
  digitalWrite(sclPin_, LOW);
  return write(addressRW);
}
//------------------------------------------------------------------------------
// issue a stop condition
void stop(void)
{
  digitalWrite(sdaPin_, LOW);
  delayMicroseconds(I2C_DELAY_USEC);
  digitalWrite(sclPin_, HIGH);
  delayMicroseconds(I2C_DELAY_USEC);
  digitalWrite(sdaPin_, HIGH);
  delayMicroseconds(I2C_DELAY_USEC);
}
//------------------------------------------------------------------------------
// write byte and return true for Ack or false for Nak
uint8_t write(uint8_t b)
{
  // write byte
  for (uint8_t m = 0X80; m != 0; m >>= 1) {
    digitalWrite(sdaPin_, m & b);
    digitalWrite(sclPin_, HIGH);
    delayMicroseconds(I2C_DELAY_USEC);
    digitalWrite(sclPin_, LOW);
  }
  // get Ack or Nak
  digitalWrite(sdaPin_, HIGH);
  pinMode(sdaPin_, INPUT);
  digitalWrite(sclPin_, HIGH);
  b = digitalRead(sdaPin_);
  digitalWrite(sclPin_, LOW);
  digitalWrite(sdaPin_, HIGH);
  pinMode(sdaPin_, OUTPUT);
  return b == 0;
}

//------------------------------------------------------------------------------
// write byte and return true for Ack or false for Nak
uint8_t ldacwrite(uint8_t b, uint8_t ldacpin)
{
  // write byte
  for (uint8_t m = 0X80; m != 0; m >>= 1) {
    // don't change this loop unless you verivy the change with a scope
    digitalWrite(sdaPin_, m & b);
    digitalWrite(sclPin_, HIGH);
    delayMicroseconds(I2C_DELAY_USEC);
    digitalWrite(sclPin_, LOW);
  }
  // get Ack or Nak
  digitalWrite(ldacpin, LOW);
  digitalWrite(sdaPin_, HIGH);
 
  pinMode(sdaPin_, INPUT);
  digitalWrite(sclPin_, HIGH);
//  digitalWrite(bsy_pin,LOW);
  b = digitalRead(sdaPin_);
  digitalWrite(sclPin_, LOW);
  digitalWrite(sdaPin_, HIGH); 
  pinMode(sdaPin_, OUTPUT);
  return b == 0;
}



void setup() {
Serial.begin(9600);
pinMode(ldac_pin,OUTPUT);
digitalWrite(ldac_pin,HIGH);
delay(10);
init (2,3);

uint8_t data1=(unsigned char)(0B11000000 | (OldAddr << 1));
uint8_t data2=(unsigned char)(0B01100001 | (OldAddr << 2));
uint8_t data3=(unsigned char)(0B01100010 | (NewAddr << 2));
uint8_t data4=(unsigned char)(0B01100011 | (NewAddr << 2));


uint8_t ack1=start(data1);
uint8_t ack2=ldacwrite(data2,ldac_pin);
uint8_t ack3=write(data3);
uint8_t ack4=write( data4);
stop();

Serial.println(data1);
Serial.println(data2);
Serial.println(data3);
Serial.println(data4);
 
Serial.println(ack1);
Serial.println(ack2);
Serial.println(ack3);
Serial.println(ack4);

delay(10);

Serial.println("FINISH");

}

void loop() {
  // put your main code here, to run repeatedly:

}
執行完畢後,請記得將Arduino 斷電,重新上電後用I2C Scanner 範例程式來確認是否有改成功。

參考來源:
https://forum.pjrc.com/threads/28424-Programming-the-I2C-address-of-a-MCP4728-4-channel-DAC-using-i2c_t3

https://github.com/TrippyLighting/SoftI2cMaster/blob/master/SoftI2cMaster.cpp