2014年1月23日 星期四

IV-18 Arduino Shield 製作


於是,IV-18 時鐘的Arduino 版登場啦~~~
經過快半個月的時間這張板子終於到了我手上,沒辦法,我真的找不到有哪一家比OSHPark便宜的PCB製作廠了

好啦,言歸正傳,這次的版本沿用http://forum.43oh.com/topic/2487-siv-18-vfd-clock-booster-pack/大致上的Layout,但是增加了DS1307 RTC,然後5V可以直接從Arduino拉過來.
首先,先上MC34063,MAX6921,DS1307,By the way,我的DS1307還沒到所以右下角沒焊接

SOIC應該不會很難焊,圖片稍微放大一點就可以發現我的焊工根本___
再來上電阻,二極體,可變電阻
剩下電容,電感,電池座和針母上完後,主體大致上就完成了
然後不想等DS1307只好把手邊的RTC模組拆了(=゚ω゚)ノ
右下角就全補齊了

再來先插上Arduino測試MC34063升壓得如何
測量點是二極體的輸出端,電壓大概20~30V就可以了,太高太低就轉可變電阻
之後換重頭戲,IV-18的轉接版~
英文不錯的話就看http://learn.adafruit.com/ice-tube-clock-kit/board-assembly這裡其中的IV-18部分吧

先上90度的雙排針,這點需要非常注意,排針要從右手邊插,如圖,如果插了的話會"非常麻煩"喔
接下來就是上IV-18
上板子之前,最好先把他的腳給剪一剪,繞一圈長度越來越短,這樣的話會比較好上去
注意到了嗎?中間有三個PIN腳是沒有功能的,這三隻PIN要插到標示在PCB上三個"NC"的地方
,插進去後,先不要焊接,把Program upload到Arduino上面,再把這個板子插到Shield上測試
測試完成後再焊接.
Program is here:GITHUB

焊接完就大功告成啦~

後來順便改一下電路板把一些缺點修一修
把有點占空間的電池座換了一個,然後有多的空間讓DS3231放背面,還有蜂鳴器也可以直接放在板子上,電感挪到MC34063旁邊
不過電池彈片還真難買.....光華繞了大半圈都沒有,只好從RS叫貨了

另外就是我發現MAX6921只能叫貨.....非常不方便,尤其是我手邊的6921快沒了
所以只好另尋他法
希望這版能測試成功

==Update==
程式碼加入了調整時間的直接方式
先輸入大寫的S,就可以進到調整時間的程式

#include <Arduino.h>

#include <Wire.h>  
#include <Time.h>  
#define DS1307_ADDRESS 0x68
#define  dataPin  11
#define  clockPin 13
#define  loadPin  5

byte zero = 0x00;
const byte segFont[] ={B00111111, B00000110, B01011011, B01001111,B01100110, B01101101, B01111100, B00000111,B01111111, B01100111, B01000000};

int lastsecond = 0;

byte bChars[10] ;
int dChars[10] ;

byte seconds;
byte hours;
byte minutes;

void serialEvent();
void setTime();
byte readByteq();
void RefreshIV18();
byte bcdToDec(byte val);
void timetoIV18(byte h,byte m,byte s);
byte decToBcd(byte val);
void printDate();

void setup()
{
  pinMode(loadPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  
  Serial.begin(9600);
  Wire.begin();
  timetoIV18(12,75,34);
  printDate();
  RefreshIV18();

}

void loop(){

  printDate();
  timetoIV18(hours,minutes,seconds);

  if (lastsecond != seconds){
   lastsecond = seconds;
   dChars[1] = !dChars[1];
   dChars[4] = !dChars[4];
   dChars[7] = !dChars[7];
   timetoIV18(hours,minutes,seconds);
 }
 RefreshIV18();

}
void serialEvent(){
int answer = Serial.read();
if (answer=='S'){
  Serial.read();
  setTime();
}
}

void setTime() {
  Serial.read();
  Serial.println("Please enter the current year, 00-99. - ");

  byte yearsett = readByteq();
  Serial.println("Please enter the current month, 1-12. - ");
  byte monthset = readByteq();
  //Serial.println(months[monthset-1]);
  Serial.println("Please enter the current day of the month, 1-31. - ");
  byte monthdayset = readByteq();
  //Serial.println(monthday);
  Serial.println("Please enter the current day of the week, 1-7.");
  Serial.println("1 Sun | 2 Mon | 3 Tues | 4 Weds | 5 Thu | 6 Fri | 7 Sat - ");
  byte weekdayset = readByteq();
  //Serial.println(days[weekday-1]);
  Serial.println("Please enter the current hour in 24hr format, 0-23. - ");
  byte hourset = readByteq();
  //Serial.println(hour);
  Serial.println("Please enter the current minute, 0-59. - ");
  byte minuteset = readByteq();
  //Serial.println(minute);
  byte secondset = 0;
  Serial.println("The data has been entered.");

  // The following codes transmits the data to the RTC
  Wire.beginTransmission(0x68);
  Wire.write(byte(0));
  Wire.write(decToBcd(secondset));
  Wire.write(decToBcd(minuteset));
  Wire.write(decToBcd(hourset));
  Wire.write(decToBcd(weekdayset));
  Wire.write(decToBcd(monthdayset));
  Wire.write(decToBcd(monthset));
  Wire.write(decToBcd(yearsett));
  Wire.write(byte(0));
  Wire.endTransmission();
  // Ends transmission of data
}


byte readByteq() {
  while (!Serial.available()) delay(10);
  byte reading = 0;
  byte incomingByte = Serial.read();
  while (incomingByte != '\n') {
    if (incomingByte >= '0' && incomingByte <= '9')
      reading = reading * 10 + (incomingByte - '0');
    else;
    incomingByte = Serial.read();
  }
  Serial.flush();
  return reading;
}
void RefreshIV18() 
  for (int count = 1;count<=9;count++){

    long data=0;
    data = segFont[bChars[count]];
    bitSet(data,17-count);
    if (dChars[count] == 1){
      bitSet(data,7);
    }
    digitalWrite(loadPin, LOW); 
  //Shiftin 20 bits
  for(byte i=0; i<20; i++) 
  { 
    //clockPin LOW
    digitalWrite(clockPin, LOW);
    //datapin bit to 1 OR 0 
    digitalWrite(dataPin,bitRead(data, i));
    //Set clockPin HIGH
    digitalWrite(clockPin, HIGH); 
  }

  digitalWrite(loadPin, HIGH);

}
}

byte bcdToDec(byte val)  {
// Convert binary coded decimal to normal decimal numbers
return ( (val/16*10) + (val%16) );
}


void timetoIV18(byte h,byte m,byte s)
{
  memset(bChars,0,sizeof(bChars));

  bChars[7]=h % 10;
  bChars[8]=h / 10;
  
  bChars[6]=10;

  bChars[4]=m % 10;
  bChars[5]=m / 10;

  bChars[3]=10;

  bChars[1]=s % 10;
  bChars[2]=s / 10;

  

}


byte decToBcd(byte val){
// Convert normal decimal numbers to binary coded decimal
return ( (val/10*16) + (val%10) );
}
void printDate(){
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.write(zero);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_ADDRESS, 3);

  seconds = bcdToDec(Wire.read());
  minutes = bcdToDec(Wire.read());
  hours = bcdToDec(Wire.read() & 0b111111); //24 hour time
   /*
  int weekDay = bcdToDec(Wire.read()); //0-6 -> sunday - Saturday
  int monthDay = bcdToDec(Wire.read());
  int months = bcdToDec(Wire.read());
  int years = bcdToDec(Wire.read());

  //print the date EG   3/1/11 23:59:59
  Serial.print(months);
  Serial.print("/");
  Serial.print(monthDay);
  Serial.print("/");
  Serial.print(years);
  Serial.print(" ");
  Serial.print(hours);
  Serial.print(":");
  Serial.print(minutes);
  Serial.print(":");
  Serial.println(seconds);
  */
}


有日期的版本:
#include <Arduino.h>

#include <Wire.h>  
#include <Time.h>  
#define DS1307_ADDRESS 0x68
#define  dataPin  11
#define  clockPin 13
#define  loadPin  5

byte zero = 0x00;
const byte segFont[] ={B00111111, B00000110, B01011011, B01001111,B01100110, B01101101, B01111100, B00000111,B01111111, B01100111, B01000000, B00000000};

int lastsecond = 0;

byte bChars[10] ;
int dChars[10] ;

byte seconds;
byte hours;
byte minutes;
int weekDay ; //0-6 -> sunday - Saturday
  int monthDay ;
  int months ;
  int years ;
void serialEvent();
void setTime();
byte readByteq();
void RefreshIV18();
byte bcdToDec(byte val);
void timetoIV18(byte h,byte m,byte s);
byte decToBcd(byte val);
void printDate();

void setup()
{
  pinMode(loadPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  
  Serial.begin(9600);
  Wire.begin();
  timetoIV18(12,75,34);
  printDate();
  RefreshIV18();

}

void loop(){

  printDate();
  datetoIV18(years,months,monthDay);

  for(int j=0;j<=1000;j++){
 RefreshIV18();
}
 timetoIV18(hours,minutes,seconds);
 for(int j=0;j<=1000;j++){
 RefreshIV18();
}

}
void serialEvent(){
int answer = Serial.read();
if (answer=='S'){
  Serial.read();
  setTime();
}
}

void setTime() {
  Serial.read();
  Serial.println("Please enter the current year, 00-99. - ");

  byte yearsett = readByteq();
  Serial.println("Please enter the current month, 1-12. - ");
  byte monthset = readByteq();
  //Serial.println(months[monthset-1]);
  Serial.println("Please enter the current day of the month, 1-31. - ");
  byte monthdayset = readByteq();
  //Serial.println(monthday);
  Serial.println("Please enter the current day of the week, 1-7.");
  Serial.println("1 Sun | 2 Mon | 3 Tues | 4 Weds | 5 Thu | 6 Fri | 7 Sat - ");
  byte weekdayset = readByteq();
  //Serial.println(days[weekday-1]);
  Serial.println("Please enter the current hour in 24hr format, 0-23. - ");
  byte hourset = readByteq();
  //Serial.println(hour);
  Serial.println("Please enter the current minute, 0-59. - ");
  byte minuteset = readByteq();
  //Serial.println(minute);
  byte secondset = 0;
  Serial.println("The data has been entered.");

  // The following codes transmits the data to the RTC
  Wire.beginTransmission(0x68);
  Wire.write(byte(0));
  Wire.write(decToBcd(secondset));
  Wire.write(decToBcd(minuteset));
  Wire.write(decToBcd(hourset));
  Wire.write(decToBcd(weekdayset));
  Wire.write(decToBcd(monthdayset));
  Wire.write(decToBcd(monthset));
  Wire.write(decToBcd(yearsett));
  Wire.write(byte(0));
  Wire.endTransmission();
  // Ends transmission of data
}


byte readByteq() {
  while (!Serial.available()) delay(10);
  byte reading = 0;
  byte incomingByte = Serial.read();
  while (incomingByte != '\n') {
    if (incomingByte >= '0' && incomingByte <= '9')
      reading = reading * 10 + (incomingByte - '0');
    else;
    incomingByte = Serial.read();
  }
  Serial.flush();
  return reading;
}
void RefreshIV18() 
  for (int count = 1;count<=9;count++){

    long data=0;
    data = segFont[bChars[count]];
    bitSet(data,17-count);
    if (dChars[count] == 1){
      bitSet(data,7);
    }
    digitalWrite(loadPin, LOW); 
  //Shiftin 20 bits
  for(byte i=0; i<20; i++) 
  { 
    //clockPin LOW
    digitalWrite(clockPin, LOW);
    //datapin bit to 1 OR 0 
    digitalWrite(dataPin,bitRead(data, i));
    //Set clockPin HIGH
    digitalWrite(clockPin, HIGH); 
  }

  digitalWrite(loadPin, HIGH);

}
}

byte bcdToDec(byte val)  {
// Convert binary coded decimal to normal decimal numbers
return ( (val/16*10) + (val%16) );
}


void timetoIV18(byte h,byte m,byte s)
{
  memset(bChars,0,sizeof(dChars));
  memset(dChars,0,sizeof(bChars));
  bChars[7]=h % 10; 
  bChars[8]=h / 10;
  bChars[6]=11;
  dChars[6]=1;

  bChars[4]=m % 10; 
  bChars[5]=m / 10;
 bChars[3]=11;
  dChars[3]=1;

  bChars[1]=s % 10; 
  bChars[2]=s / 10;

  

}
void datetoIV18(int yy,int mm,int dd)
{
  memset(dChars,0,sizeof(dChars));
  memset(bChars,0,sizeof(bChars));

  bChars[8]=yy/10;
  bChars[7]=yy%10; 
  
  bChars[6]=10;

  bChars[5]=mm/10; 
  bChars[4]=mm%10;

  bChars[3]=10;

  bChars[2]=dd / 10;
  bChars[1]=dd % 10; 

}


byte decToBcd(byte val){
// Convert normal decimal numbers to binary coded decimal
return ( (val/10*16) + (val%10) );
}

void printDate(){
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.write(zero);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_ADDRESS, 7);

  seconds = bcdToDec(Wire.read());
  minutes = bcdToDec(Wire.read());
  hours = bcdToDec(Wire.read() & 0b111111); //24 hour time
  
   weekDay = bcdToDec(Wire.read()); //0-6 -> sunday - Saturday
  monthDay = bcdToDec(Wire.read());
  months = bcdToDec(Wire.read());
   years = bcdToDec(Wire.read());
/*
  //print the date EG   3/1/11 23:59:59
  Serial.print(months);
  Serial.print("/");
  Serial.print(monthDay);
  Serial.print("/");
  Serial.print(years);
  Serial.print(" ");
  Serial.print(hours);
  Serial.print(":");
  Serial.print(minutes);
  Serial.print(":");
  Serial.println(seconds);
  */
}

2014年1月10日 星期五

TPS62203 6V降壓板

這東西真是難搞,最主要就是那個電感太太太太太難焊接了,只好把插件的東西當SMD用


新的DS2764鋰電池電量管理PCB

改成自己送洗的PCB體積變得好小,這次順便把 P Mosfet 加回去,用的是TPS1120 dual p mosfet

2014年1月3日 星期五

ADUM4160 USB 電源隔離器

總之這東西可以把USB的訊號完全隔離,包含地線也可以切開,可以防止電腦搞換USB儀器或是可以阻止電腦的供電雜訊到USB裝置裡,這次送洗完覺得....USB公頭的PCB邊緣要再縮小一點...
不然沒辦法完全180度還滿糟糕的

PCM5102a DAC

我一直很想要做一個i2s介面的DAC,原先的PCM2706 USB DAC原本就是為了i2S輸出做的
以前的DAC IC 例如最高級的PCM1794 通常在輸出端都還要加I/V轉換以及LPF
算一算就需要六個OPA來處理了,現在我還沒到那個功夫處裡(也沒那個錢去送洗那麼大張的電路).前陣子發現了PCM5102a這個IC ,內建了I/V轉換,輸出端也只需要電容+電組的簡易LPF
電路簡單容易兜,所以就開工了

電路多簡單呢?
可以放在一個迷你麵包版的電路阿XDDD


IV-18 VFD 真空管時鐘


是的,我又做了一個真空管時鐘
這次是做VFD的版本,利用IV-18 booster pack + 放置PLAY很久的MSP430

先介紹IV-18吧

蘇聯製最大隻的VFD真空管,包含8個數字(含小數點)及一個指示點
比起Nixie 的 IN-18 ,可說是便宜很多啊(這隻含運200~300)
這隻VFD管的接腳一共20隻,包含9個選擇位數的+8個7段顯示器含小數點的腳+三個dummy
看到這應該可以想像驅動方式是掃描式了吧XD

至於驅動方式,引用http://led.eefocus.com/article/10-07/1459731278923416.html這篇文章的圖
燈絲通電後電子衝出來,經過欄極加速後,衝到陰極,如果通電的話就撞上去,撞到螢光粉發光
通常燈絲電壓為5V,欄極與陰極為30V左右(每種都不太一樣)

所以驅動這管子,需要有能夠輸出30V給VFD管的IC,這個版本用的是MC34063升壓IC,以及MAX6921 VFD 專用驅動IC,
MC34063將5V升到大約30V後,供電給MAX6921,MAX6921一共20個輸出腳位(by the way 我們只要用到 17個)至於燈絲電流,加個限流電阻就直接接VFD

MAX6921的驅動方式很簡單,就像SPI一樣,給個CLOCK+DATA還有幾個控制腳就可以了
VSS的負電壓沒有用到
LOAD高電壓的時候傳送資料由DIN+CLK傳送,而BLANK為高電壓時會強制輸出為0

至於RTC就用MSP430內建的電路,只要外接震盪器就可以用了

順帶一提,Arduino shield 已經送洗了XDDD 好期待

TLC5940 LED版

摁..其實是手上LED燈滿多的所以就做個16LED版來用,想要拿來做成光影藝術的裝置或是啥的
這個電路也是送洗了,畢竟我家是不准自己洗電路板的(化學藥劑....)
電路基本上就是TLC5940 + 16個 單色 5050 SMD LED

Arduino 無線氣象站 Ver3.0

好久沒動這個部落格了...總覺得是時候該整理一下最近做的

先來說這次天氣站改版吧,這次修改幅度可謂最大的一次
改版的目標是將耗電量盡可能的降低
為了達到目標,首先,無線模組換成了nRF24l01,
再來,Arduino的版本換成了3.3V的版本,取消了鋰電池升壓板,換成了一個LDO增加效率
然後,為了減少接線的麻煩,我去送洗了這個版本的PCB
感應器列表:

  • BMP085 大氣壓力計
  • DHT22   溫溼度感應器
  • ADT7140 溫度感應器
  • 預留i2C以及電源可外接

輸入程式中的主機板完成品
不過送洗回來後才發現很多悲劇的地方....
首先,DHT22的腳位為啥會朝內阿阿阿阿阿
再來,Tx Rx放反了阿阿阿阿阿阿阿
最後.....DTR的電容忘了加...(眼神死
不過勉強還可以用就是了  Orz
還有一個太陽能板沒上
nRF24l01真的比較好用...至少傳資料比較不會錯
而且可以Power Down到uA等級,Start up 也很快,只是接收端就需要Arduino來解碼就是了
raspberry pi 應該可以直接接nRF24l01解碼,但是我還不會用XD
因應通訊模組的更換,Raspberry pi 上的Python code也順便換了
這次除了送Data到Cosm以外,還有存到CSV檔,另外就是送上Google Docs(這個副程式目前有問題)

感應器的耗電量如下
  • Power Save     60uA
  • Tx                   10mA
  • 測量中      ~2~8mA
總結來說,一天的耗電量可以壓到10mAh沒問題,但是改進的地方還很多
Power Save mode 可能因為AMS1117-3.3V 的轉換效率在極低電流的時候漏電流的關係
以及Arduino沒有關掉BOD,耗電量其實是有點大的
再來,讀取資料的時候DHT22需要delay 2秒,其實是可以把其他資料讀完的,減少讀取時間
最後,nRF24l01送資料的時候可以簡化Package,減少Tx的時間

以上

====Arduino weather station ver 3.0===
Update: 我把DS2764的鋰電池管理PCB換成送洗的版本,以及加強固定