W!o+ 的《小伶鼬工坊演義》︰ 一窺全豹之系統設計《童子問》

易童子問第一

乾,元亨利貞

童子問曰:「乾,元亨利貞」何謂也?

曰:眾辭淆亂,質諸聖。《彖》者,聖人之言也。

童子曰:然則《乾》無四德,而《文言》非聖人書乎?

曰:是魯穆姜之言也,在襄公之九年。

 

假使思考歐陽修為什麼寫《易童子問》?

歐陽修(1007年-1072年),字永叔,號醉翁、六一居士,諡文忠,北宋吉州廬陵(今屬江西省永豐縣)人。(歐陽修生平請參考維基百科

所著《易童子問》三卷,收錄於《歐陽文忠公集》(或簡稱《文忠集》)第七十六至七十八卷,以問答的方式表達其對於《易經》的一些見解。每個問題都以「童子問」做為開始。

文忠公是第一位對於《十翼》以及諸如「四元德」等傳統見解提出質疑與抨擊的大儒,而這些見解也影響了後世許多學者,甚至得到近現代許多學者考證的支持。

除了較為知名的《易童子問》三卷之外,易學網另外也收錄《文忠集》中其他與《易經》相關的論述,以完整呈現歐陽修對《易經》所提出的見解。

,難到不因懷疑也!『聖人』也是『人』??果能『全知』乎!!

今想 GrovePi 之『軟體架構』,當真『奇怪』耶︰

 

【為什麼需要 Dummy Byte ?】

dataformat

 

因為 SMBus 的

I2C Access Functions

long[] read_i2c_block_data( int addr, char cmd )
Block Read transaction.

write_i2c_block_data(int addr, char cmd,  long vals[])
Block Write transaction.

 

,需要『 char cmd 』參數!所以

【 API 】

# Function declarations of the various functions used for encoding and sending
# data from RPi to Arduino

# Write I2C block
def write_i2c_block(address, block):
        try:
                return bus.write_i2c_block_data(address, 1, block)
        except IOError:
                if debug:
                        print ("IOError")
                return -1

# Read I2C byte
def read_i2c_byte(address):
        try:
                return bus.read_byte(address)
        except IOError:
                if debug:
                        print ("IOError")
                return -1


# Read I2C block
def read_i2c_block(address):
        try:
                return bus.read_i2c_block_data(address, 1)
        except IOError:
                if debug:
                        print ("IOError")
                return -1

 

【韌體】

void receiveData(int byteCount)
{
    while(Wire.available())
    {
    if(Wire.available()==4)
    {
      flag=0;
      index=0;
              run_once=1;
    }
      cmd[index++] = Wire.read();
    }
}

 

配合著寫,或可 I2C 通訊校核?且有其他用途的哩??

 

【為什麼傳回值也有 Dummy Read ?】

def analogRead(pin):
bus.write_i2c_block_data(address, 1, aRead_cmd + [pin, unused, unused])
time.sleep(.1)
bus.read_byte(address)
number = bus.read_i2c_block_data(address, 1)
time.sleep(.1)
return number[1] * 256 + number[2]

 

因為『統整』一與多之故。考之以韌體『流程』︰

// callback for sending data
void sendData()
{
  if(cmd[0] == 1)
    Wire.write(val);
  if(cmd[0] == 3 || cmd[0] == 7 || cmd[0] == 56)
    Wire.write(b, 3);
  if(cmd[0] == 8 || cmd[0] == 20)
    Wire.write(b, 4);
  if(cmd[0] == 30)
    Wire.write(b, 9);
  if(cmd[0] == 40)
    Wire.write(dht_b, 9);
  if(cmd[0]==21)
  {
    Wire.write(b,21);
    b[0]=0;
  }
  if(cmd[0]==dust_sensor_read_cmd)
  {
    Wire.write(b,4);
    dust_latest=0;
    cmd[0]=0;
  }
  if(cmd[0]==encoder_read_cmd)
  {
    Wire.write(enc_val,2);
    enc_val[0]=0;
    cmd[0]=0;
  }
  if(cmd[0]==flow_read_cmd)
  {
    Wire.write(flow_val,3);
    flow_val[0]=0;
    cmd[0]=0;
  }
}

 

,察之以 API 『改寫』︰

# Read analog value from Pin
def analogRead(pin):
        bus.write_i2c_block_data(address, 1, aRead_cmd + [pin, unused, unused])
        time.sleep(.1)
        temp = bus.read_byte(address)
        print (temp)
        number = bus.read_i2c_block_data(address, 1)
        print (number)
        time.sleep(.1)
        return number[1] * 256 + number[2]

# Read value from Grove Ultrasonic
def ultrasonicRead(pin):
        write_i2c_block(address, uRead_cmd + [pin, unused, unused])
        time.sleep(.2)
        temp = read_i2c_byte(address)
        print (temp)
        number = read_i2c_block(address)
        print (number)
        return (number[1] * 256 + number[2])

 

證之以『實務』結果︰

Python 2.7.9 (default, Mar  8 2015, 00:52:26) 
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import grovepi
>>> potentiometer = 0
>>> grovepi.pinMode(potentiometer,"INPUT")
1
>>> sensor_value = grovepi.analogRead(potentiometer)
0
[0, 2, 191, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
>>> sensor_value
703
>>> ultrasonic_ranger = 4
>>> print grovepi.ultrasonicRead(ultrasonic_ranger)
0
[0, 0, 198, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
198
>>> 

 

那麼下文又將怎麼說的呢?

# Arduino Digital Read
def digitalRead(pin):
        write_i2c_block(address, dRead_cmd + [pin, unused, unused])
        time.sleep(.1)
        n = read_i2c_byte(address)
        return n

def dustSensorRead():
        write_i2c_block(address, dus_sensor_read_cmd + [unused, unused, unused])
        time.sleep(.2)
        #read_i2c_byte(address)
        #number = read_i2c_block(address)
        #return (number[1] * 256 + number[2])
        data_back= bus.read_i2c_block_data(address, 1)[0:4]
        #print data_back[:4]
        if data_back[0]!=255:
                lowpulseoccupancy=(data_back[3]*256*256+data_back[2]*256+data_b$
                #print [data_back[0],lowpulseoccupancy]
                return [data_back[0],lowpulseoccupancy]
        else:
                return [-1,-1]
        print data_back

 

,難不成還有『未公開』 undocumented 之事嘛!

 

【為什麼新舊韌體所得不一?裝置組合結果不同??】

請參考

Ultrasonic Ranger 1.0 Broken ?

討論。然後測之以其法

# Read value from Grove Ultrasonic
def ultrasonicRead(pin):
        write_i2c_block(address, uRead_cmd + [pin, unused, unused])
        time.sleep(.2)
        read_i2c_byte(address)
        number = read_i2c_block(address)
        if type(number) is list : return (number[1] * 256 + number[2])
        else: return -1

 

似乎較好。若是考以不同『裝置組合』,為什麼『超聲波測距儀』 Ultrasonic Ranger 與『繼電器』 Relay 分接『三、七』可以!但是『二、八』卻不行的呢?

再三設想那個韌體程式︰

    //Ultrasonic Read
    else if(cmd[0]==7)
    {
      pin=cmd[1];
      pinMode(pin, OUTPUT);
      digitalWrite(pin, LOW);
      delayMicroseconds(2);
      digitalWrite(pin, HIGH);
      delayMicroseconds(5);
      digitalWrite(pin,LOW);
      pinMode(pin,INPUT);
      dur = pulseIn(pin,HIGH);
      RangeCm = dur/29/2;
      b[1]=RangeCm/256;
      b[2]=RangeCm%256;
      //Serial.println(b[1]);
      //Serial.println(b[2]);
    }

 

,雖然不知

Grove – Ultrasonic Ranger

之『電路原理』,這個

『 dur = pulseIn(pin,HIGH); 』

,真的不會『出錯』嗎?!或許某些『答案』只得回到『故紙堆』中找耶??!!

 

【 Arduino Wire 程式庫】

:: Wire Library, Explored

An indepth reference to the Arduino Wire library.

Introduction

Greetings, fellow Arduinoid! GreyGnome here. The Arduino Wire library documentation is notoriously stingy in details. Nowhere does it explain its relationship to the twi library of the avr-lib, and worse, to the TWI hardware in the ATmega chips. This reference attempts to fill in the gaps and give the Wire library the documentation it needs and deserves.

Throughout the exploration of the code and the design of this document, this author has used the Arduino Duemilanove, based on the ATmega328 datasheet. See the ATmega328 datasheet for more information. It is an invaluable reference for understanding the TWI hardware and the ATmega‘s I2C communication methodology.

………

 

【 ATmega CPU DataSheet 】

ATmega48A/PA/88A/PA/168A/PA/328/P