2018年2月8日 星期四

Arduino 4位數7段LED數字顯示器

最近做了幾個專案都使用Arduino, 有位同仁也對Arduino產生了學習的興趣, 他自己嘗試用74HC595移位器可以驅動一位數7段LED, 但在4位數的就是動不了, 要我幫忙看一下。

所以整理這幾日看的資料:

1. 7段LED的原理:
以下這個連結的文章, 寫得不錯!
介紹1位數7段LED原理
  (1) 原來是用7個LED燈, 加上小數點就是8個LED燈來組成數字
  (2) 有分共陽(common anode), 共陰(common cathode)兩種作法
  (3) 所以會用掉Arduino的8個數位輸出

2. 4位數7段的LED:
這篇介紹4位數的部份, 4位數7段LED(common anode)
  (1) 說明4位數的作法是多工的方式, 和原本一位數的作法一樣, 也是要8個數位輸出
  (2) 但是只再多使用D1, D2, D3, D4(4位數7段LED的腳位)共四個腳位, 用來指示要將8個segment的輸出送到那一個位數。
  (3) 使用電晶體(NPN)來加大輸出的電流能力, up side switch (sourcing current)
  (4) 會用掉Arduino的所有數位輸出腳位

這篇的作法有點不一樣, (common cathode)
http://www.electroschematics.com/10512/arduino-4-digit-7-segment-led-display/
  (1) 一樣加入4個電晶體(NPN), 但是做成down side switch(sinking current)
  (2) 程式寫法幾乎和前一篇的相同, showDigit()裡的作法改成common cathode

3. 減少使用Arduino數位輸出的方法, 使用74HC595
這篇文章有詳細的說明: Arduino_74HC595
  (1) 595可以讓Arduino只使用3支腳就可以控制8個LED燈
  (2) 還可以用串2個595的方式, 增加到可以控制16個LED燈

4. Arduino內建支援595的使用函數
這篇文章有介紹: https://www.arduino.cc/reference/en/language/functions/advanced-io/shiftout/

5. 整合以上
  電路部份主要依  4位數7段LED(common anode)
  但是 因拿到的4位數7段LED為common cathode
  所以電晶體接法採用 http://www.electroschematics.com/10512/arduino-4-digit-7-segment-led-display/
  另外加入74HC595以減少使用Arduino數位輸出腳位
  稍為有調整使用到的腳位

  搭配的Arduino程式碼如下:

const int sensorPin= 0;//The analog sensor is connected to analog pin 0 of the arduino

//ABCDEFG,dp
const int numeral[10]= {
B11111100, //0
B01100000, //1
B11011010, //2
B11110010, //3
B01100110, //4
B10110110, //5
B00111110, //6
B11100000, //7
B11111110, //8
B11100110, //9
};

//pins for decimal point and each segment
//dp, G, F, E, D, C, B, A
const int segmentPins[]= { 13, 7, 8, 6, 5, 3, 2, 4};

const int numberofDigits=4;

const int digitPins[numberofDigits] = { 9, 10, 11, 12}; //digits 1, 2, 3, 4

//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 7;
////Pin connected to DS of 74HC595
int dataPin = 6;

void setup()
{
  //for (int i=0; i < 8; i++)
  //  pinMode(segmentPins[i], OUTPUT); //set segment and DP pins to output

  //sets the digit pins as outputs
  for (int i=0; i < numberofDigits; i++)
    pinMode(digitPins[i], OUTPUT);

  //set pins to output because they are addressed in the main loop
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
}

void loop()
{
  /*
  for (int i=0; i<=9999; i++) {
    //for (int j=0; j<4 j="" p="">    for (int k=0; k<50 k="" p="">      showNumber(i);
      //showDigit(2, j);
    }
    //}
  }
  */
  int value= analogRead(sensorPin);
  for (int k=0; k<100 k="" p="">    showNumber(value);
  }
  //delay(100);
}

void showNumber (int number)
{
  if (number == 0)
    showDigit (0, numberofDigits-1); //display 0 in the rightmost digit
  else
  {
    for (int digit= numberofDigits-1; digit >=0; digit--)
    {
      if (number > 0)
      {
        showDigit(number % 10, digit);
        number= number/10;
      }
    }
  }
}

//Displays given number on a 7-segment display at the given digit position
void showDigit (int number, int digit)
{
  //pinMode(digitPins[digit], OUTPUT);
  digitalWrite(digitPins[digit], HIGH);

  //ground latchPin and hold low for as long as you are transmitting
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, LSBFIRST, numeral[number]);
    //return the latch pin high to signal chip that it
    //no longer needs to listen for information
    digitalWrite(latchPin, HIGH);
 
  /*
  for (int segment= 1; segment < 8; segment++)
  {
    boolean isBitSet= bitRead(numeral[number], segment);

   // isBitSet= ! isBitSet; //remove this line if common cathode display
    digitalWrite(segmentPins[segment], isBitSet);
  }
  */
  delay(5);
  digitalWrite(digitPins[digit], LOW);
  //pinMode(digitPins[digit], INPUT);
}

Macbook NVRAM Reset 解決問題經驗

最近我的Mac Book碰到幾個狀況,後來都是用NVRAM Reset 解決的:

1 公司的Macbook Pro 2013,收到Apple的軟體更新通知,做了更新後,開機開不起來,或者開機開超級久。

2 家裡的MacBook 2008, 系統和看網頁變慢, 看系統活動, 發現system cpu usage佔了50%, 再細查發現這是kernel_task在使用, 但看不出是那一支特定的程式在用。網路上有人說, 是過熱或者硬體有問題等, 也有人說NVRAM Reset可能有幫助。用電扇吹了很久, 電腦都冷冰冰了, 還是一樣, 結果NVRAM Reset後就正常。以前開機開很久的問題也解決了。


NVRAM Reset 方法:
https://support.apple.com/zh-tw/HT204063

2018年1月13日 星期六

用Atmega 328p 自組Arduino上傳草稿碼時, 如何自動Reset?


Arduino開發板玩了一陣子之後, 會想要自己組一個開發板。
參考做法: https://www.arduino.cc/en/Main/Standalone

這樣的好處是:
1. 省錢
  開發板比較貴, ATMega328P晶片比較便宜
2. 省電
  要做低粍電專案, 開發板粍電量太高
3. 好玩

但是寫完草稿碼後, 要上傳時; 以前看葉大的書, 叫我們自己找正確的時點去Reset晶片。
手動Reset的日子, 我也過了不少, 但有時太常改程式, 又不太抓得到時點, 會一直上傳失敗。

所以就想人家開發板為什麼不用手動Reset, 可以自動Reset?
發現其實只是將Serial-to-USB的RTS接腳, 接一個100nF的電容, 再接到328p晶片的Reset腳位就好。


參考來源: 電路圖

直接用來看看, 是真的可以運作的! 只是加個電容就好了, 真是神奇!
可是我用來有時也會失敗!
又Google了一下, 發現別人也有類似情形, 有人就加上拉電阻及下接電阻。
我後來查了一下Arduino官方電路圖:
https://www.arduino.cc/en/uploads/Main/Arduino_Nano-Rev3.2-SCH.pdf

也是一樣做法!

就不管了, 那就這樣接吧, 後來把breadboard的元件用洞洞板焊接後, 發現上傳的成功率居然變得很高! 所以我的想法是: breakboard可能有些接觸不良的情形, 用焊接的就消除這個問題, 只是我的Serial-to-USB板子接到洞洞板做的成品時, 仍是用插接的, 加上電容也是臨時用杜邦線接的, 也會有接觸不良問題, 才造成部份的失敗率!


2018年1月9日 星期二

MacOs High Sierra CH340

今天我的Mac當機好幾次了!
原本好好的程式,今天一直出問題,移到Windows用,又好好的沒事。
才想到是不是Mac出問題,問了google
原本真的是Mac有問題!

http://www.stm32duino.com/viewtopic.php?t=1684

後來發現不全然是Mac的問題, 主要還是我接的Arduino板子, 其實還有其他外加元件和電路; 而這些電路本身的設計有些問題。主要的問題是電流或電壓在某些狀況下不太正常。會造成Arduion板子自己reset或行為異常, 這個現象在Mac上的結果會是當機重開! 有趣的是在Windows 10上卻不會有問題出現。

修改電路接法, 再重試後, 就不會當機了。


2017年12月13日 星期三

什麼patch?要怎麼用?

今天收到一個*.patch的檔案, 因為之前廠商有一個範例程式有些問題。
他們做了一些修正。

我本以為他們會把整包改好的程式丟過來, 沒想到是用patch!

如果是Linux/Unix的環境, 本來就是常用patch來做程式的異動,
但他們的環境一直都是在Windows上面的。

這下子真不知如何做了, 找了一下, 發現:

https://stackoverflow.com/questions/517257/how-do-i-apply-a-diff-patch-on-windows

有人介紹在Windows可以用Python工具來做:
pip install patch
python -m patch
於是照做:
先把*.patch檔copy到原先的程式, projects目錄的上一層.
因為我在.patch檔看到如下的內容:

diff --git a/projects/target_apps/ble_examples/ble_app_barebone/src/user_barebone.c

想來是用相對目錄, 就如此做了, 也不知有沒有必要如此?

然後下如下指令:

G:\DA14585_SDK\6.0.4.326>python -m patch 20171120_0_ancs.patch

沒有出現任何成功或失敗的訊息!
用人工去檢查, 結果是成功的做好了!


2017年12月2日 星期六

Myth about ADXL345 breakout


  This is my experience about buying AD's ADXL345 accelerometer breakout board.

  There are so many breakout boards of ADXL345 sold in the market (or shopping store). Some are very cheap and some are very expensive. Price ranges from NT$ 65 to NT$799. Which one should you buy? What's the difference between the cheap one and expensive one?


  I choose to take adventure and buy the cheaper breakout, one for NT$ 65 and one for NT$ 85. And the result, the NT$ 65 one can't work! But the NT$ 85 one work perfectly.


  As the picture shows, this ADXL345 breakout board work! The acceleration reading values can be read out. At first I use ST's Nucleo-F401RE development board to connect this NT$ 85 ADXL345 breakout board via SPI interface. And in the MBED online compile web site, I import the ADXL345_HelloWorld sample program to read out acceleration readings.

  The first time I run that program, nothing can be readout. Strange! Check the schematic (show below), I found SDO (pin 12) was connect to ground.
85元便宜ADXL345板子電路圖

  So this is the problem come from. Don't hesitate, use your torch to remove resistor R4. And try again. This time the readings was correct. But in the internet, I found some blog say that NT$ 85 breakout can't work with SPI. He say this kind of cheap breakout just work with I2C. I was confused! Because the same breakout is working fine via SPI in front of me.

  Recently I have opportunity to experiment this cheap ADXL345 breakout with Arduino Uno board. Because Arduino Uno board is 5 voltage system, and ARM Cortex is 3.3 voltage system. It worth to give it a try. But first, I check Sparkfun's web site about their ADXL345 breakout board. They have demonstrate how to connect Arduino Uno board with their breakout via both SPI and I2C.
Sparkfun's ADXL345 breakout

So, what's the difference between Sparkfun's breakout and the cheap one?
The NT$ 85 cheap breakout

Just using our eye, we see that the number of components in the cheap breakout are much more that the Sparkfun's breakout.
SparkFun ADXL345板子的電路圖

Yes, there are just 3 capacitors in addition to the ADXL345 chip at the Sparkfun's breakout. Nothing special. No reason it can work with SPI, but the cheap one can't.
Let's make experiment to see result.

I2C界面接法
wiring via I2C

Wiring via I2C work fine. The wiring char and sample code is here: https://github.com/poushen/adxl345_i2c

SPI界面接法
wiring via SPI

Wiring via SPI:
1. Connect Arduino Uno board's SPI pins directly with the cheap breakout's SPI pins don't work. Check Sparkfun's web site, I find they use voltage level translator.
2. Using TI's TXB0104 to do the work of voltage level translator, the readings is not correct. Check the TXB0104's document, see it's sensitive to pull-up resistor. And the cheap breakout do have 10K pull-up resistor at SDA, SCL, CS pins.
3. Using bidirectional logic level converter (BD-LLC), it work perfectly! The wiring char and sample code is here: https://github.com/poushen/adxl345_spi
BD-LLC document is here: https://learn.sparkfun.com/tutorials/bi-directional-logic-level-converter-hookup-guide

In conclusion, the cheap ADXL345 breakout can connect via SPI.

  The cheap breakout was designed for I2C wiring, so it give us pull-up and pull-down resistor out of box. But it work with SPI too. Just remove R4 pull-down resistor and using BD-LLC, we can make it work with SPI. Oops, you want to use TI's TXB0104. Ok, I think it would be also work. But you must remove more resistor. See https://learn.sparkfun.com/tutorials/txb0104-level-shifter-hookup-guide

Adafruit的板子

  Now let's look at Adafruit's ADXL345 breakout board. In addition to voltage regulator and pull-up pull-down resistor, it also have voltage level shifter build in. With some other circuit design, it let you   easier to connect with Arduino Uno via SPI or I2C. Adafruit indeed is more intimate. So, which breakout board will you choose? Cheap one or expensive one?

Whatever you choose (or buy), don't forget that Spartfun and Adafruit had ADXL345 sample code and library for you (it's free too). Of course, you can write the code by yourself. Just like those I put in GitHub. Also, don't forget Analog Devices ADXL345 official web site. There are so many documents. http://www.analog.com/en/products/mems/accelerometers/adxl345.html

2017年11月22日 星期三

升級到MacOS High Sierra? ftp會不見哦!

今天忍不住了,還是升級到MacOS High Sierra
果然沒事找事,一升級就會出問題!

居然終端機裡的ftp不見了,當下心想,又是Apple自己改的!
找了一下,果然如此:

https://discussions.apple.com/thread/8093031?start=0&tstart=0

那怎麼辦呢?
上面討論串的最後,有朋友提了一個方法,就是安裝LFTP來頂著用:
$ brew install inetutils

will install inetutils from GNU that includes /usr/local/bin/ftp

$ which ftp
/usr/local/bin/ftp
$ ftp --version
ftp (GNU inetutils) 1.9.4
Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by many authors.
要先安裝brew:
https://brew.sh/

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

順利裝好。

然後下 $ brew install inetutils
結果:
Error: Your Xcode (8.2) is too outdated.
Please update to Xcode 9.1 (or delete it).

Xcode can be updated from the App Store.

原因是之前為了玩深度學習Tensorflow的nVidia GPU計算功能,把xcode command line工具的路徑固定到8.2版去了,那現在只好改回來:

$ sudo xcode-select --switch /Applications/Xcode.app

再重下之前指令,就好了:
$ brew install inetutils
==> Installing dependencies for inetutils: libidn
==> Installing inetutils dependency: libidn
==> Downloading https://homebrew.bintray.com/bottles/libidn-1.33.high_sierra.bottle.tar.gz
######################################################################## 100.0%
==> Pouring libidn-1.33.high_sierra.bottle.tar.gz
==> Caveats
Emacs Lisp files have been installed to:
  /usr/local/share/emacs/site-lisp/libidn
==> Summary
🍺  /usr/local/Cellar/libidn/1.33: 72 files, 1.3MB
==> Installing inetutils
==> Downloading https://homebrew.bintray.com/bottles/inetutils-1.9.4.high_sierra.bottle.1.tar.gz
######################################################################## 100.0%
==> Pouring inetutils-1.9.4.high_sierra.bottle.1.tar.gz

🍺  /usr/local/Cellar/inetutils/1.9.4: 107 files, 2.6MB