W!o+ 的《小伶鼬工坊演義》︰ 一窺全豹之系統設計‧探索‧丙

甲骨文丁一

甲骨文丁二

甲骨文丁三

説文解字》:,夏時萬物皆丁實。象形。丁承丙,象人心。凡丁之屬皆从丁。

本義︰竹木或金屬製成之頂寬足尖的契子。

─── 見於《《派生》 Python 作坊【丁】陽燧月鑑

 

話說眼尖心細的讀者,早已看出上篇『補丁』,對『 read_i2c_block 』而言,恐將不受『 index==4 』的管制︰

void loop()
{
  long dur,RangeCm;
  if(index==4)
  {
    flag=1;
    //IR reciever pin set command
    if(cmd[0]==22)
       IR.Init(cmd[1]);

…………

    if(flow_run_bk)
    {
        if(millis()-flow_read_start>2000)
        {
            Calc = (NbTopsFan * 30 / 73);
            flow_val[0]=1;
            flow_val[1]=Calc%256;
            flow_val[2]=Calc/256;
            NbTopsFan = 0;
            flow_read_start=millis();
        }
    }
}

 

。要是想『 CMD=1 』是『 Digital Read 』指令,或可『無礙』乎?由於作者尚未能深思熟慮,故而祇想以最少『修補』爾爾!更何況這也方便探究其與『 Digital Read 』之『差別』也??

【 digitalRead vs. read_i2c_block 】

>>> switch=3
>>> grovepi.pinMode(switch,"INPUT")
1
>>> grovepi.digitalRead(switch)
0
>>> grovepi.read_i2c_block(addr)
[11, 2, 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, 255]
>>> grovepi.read_i2c_block(addr)
[11, 190, 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, 255]
>>> grovepi.read_i2c_block(addr)
[11, 0, 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, 255]
>>> grovepi.read_i2c_block(addr)
[11, 0, 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, 255]
>>> grovepi.read_i2c_block(addr)
[11, 0, 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, 255]
>>> grovepi.read_i2c_block(addr)
[11, 0, 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, 255]
>>> grovepi.digitalRead(switch)
0
>>> grovepi.ultrasonicRead(ultrasonic_ranger)
0
[11, 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
>>> 

>>> grovepi.bus.write_i2c_block_data(5, 1, [3] + [0, 0, 0])
>>> grovepi.bus.read_i2c_block_data(5, 1)
[11, 2, 190, 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]
>>> grovepi.bus.write_i2c_block_data(5, 1, [3] + [0, 0, 0])
>>> grovepi.read_i2c_byte(addr)
0
>>> grovepi.bus.read_i2c_block_data(5, 1)
[11, 2, 190, 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]
>>>

 

CMD = 5, index =  4

CMD = 1, index =  4

DATA = 0, 2, 189

CMD = 1, index =  0

CMD = 1, index =  1

CMD = 1, index =  2

CMD = 1, index =  3

CMD = 1, index =  4

CMD = 1, index =  0

CMD = 1, index =  4

DATA = 0, 2, 189

CMD = 7, index =  4

DATA = 0, 0, 198

CMD = 7, index =  0

#
CMD = 3, index = 4

CMD = 3, index = 0

CMD = 3, index = 4

DATA = 0, 2, 190

CMD = 3, index = 0

#

 

竟然『 read_i2c_block 』不經『 read_byte() 』洗禮,不能觸動

void sendData()

機制。如是面對『問題』 issues 時,

Extraneous bus.read_byte commands? #169

In various functions in grovepi.py, there are what seem to me to be completely extraneous calls to read_byte, which can just be deleted. Or at least, deleting them doesn’t seem to break anything for me.

e.g. in analogRead it says bus.read_byte(address), then it does the actual read transaction with number = bus.read_i2c_block_data(address, 1). As far as I can tell the bus.read_byte is totally ignored, just does an extra i2c transaction for no reason and makes the code slightly slower.

Maybe I’m missing something and there is a reason for it, but as far as I can tell this is a bug?

 

When we were building the firmware initially, we found that read_block() didn’t work properly without calling the read_byte() first and this was the way we were able to make it work. It was a workaround then and we seem to have kept it till now.

 

是否足以做出『判斷』呢?到底現今還需要『 Dummy Read 』的嗎 ??或許樹莓派論壇上的一篇古老討論︰

I2C clock stretching

by stefanBA » Mon Aug 06, 2012 9:44 pm

Hello!

I’m trying to use I2C to connect an ATmega8A microcontroller as an I2C slave to the RasPi. However, I’m experiencing problems with the clock stretching feature of I2C. Whenever the microcontroller is not able to execute the I2C interrupt fast enough, it holds the clock line low to make the I2C master (RasPi) wait. This feature is supported by RasPi according to the BCM2835 ARM Peripherals data sheet (section 3.1, page 28).

However, when the I2C slave actually stretches the clock (e.g. by 4 us), the RasPi seems to ignore it and generates the next falling clock edge without any further delay (e.g. 1 us after the slave released the clock line to high). The sampling of the data line also seems to happen at the time the regular (i.e. un-stretched) positive edge of the clock would have occured.

I’m using raspbian OS and bootc’s kernel 3.2.23+. Although the I2C driver never detects a clock stretching timeout, I’ve tried to change the value of the clock stretch timeout register (CLKT) in the driver. I changed the default value of 0x40 to larger values (0x400, 0x4000) and also set it to zero to turn off clock stretch timeout detection. It did not change the behaviour.

Did anybody else experience a similar behaviour?

Does anybody know what I could be doing wrong?

Best regards,
Stefan

───

by Gert van Loo » Thu Aug 09, 2012 4:42 pm

Ok, here I am, one day late but I have most of the answers from the developers mouth.

There is a bug in the I2C master that it does not support clock stretching at arbitrary points.
It does support clock stretching during the ACK phase.

I hope this clarifies it’s behavior.

───

by Frank B » Mon Oct 08, 2012 6:34 pm
pico wrote:I’m trying to comminucate with an atmega328p (Arduino clone) as an i2c slave.

Did you see the errata in the atmega328p-datasheet ? There’s a silicon-bug in the mega328p too…(when acting as slave)

Two bugy i2c-silicons are talking to each other… :D

I would try with very low speeds to see if it works, and then slowly go higher.

Frank.
p.s. i would be interested in your results – i plan to use an arduino.

 ───

 

,說明了相關『問題』的複雜性!!也許這篇

Raspberry Pi I2C clock-stretching bug

Date: 2013-08-17

Summary

The Broadcomm BCM2835, which is used on the Raspberry Pi, has a serious bug in its I2C implementation, which can (a) prevent I2C communication with some devices and (b) lead to data corruption (both in read and write direction).

As a result, do not use I2C-devices which use clock-stretching directly with the Raspberry Pi directly or any other Broadcomm BCM2835-based device.

Fix:
None
Workarounds:
see below

………

 

文章固可以『釋疑』,卻是無法『解惑』的也耶??!!

當思活在『 buggy 』的世界裡,請隨時準備好『 work arround 』的哩!!!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

W!o+ 的《小伶鼬工坊演義》︰ 一窺全豹之系統設計‧探索‧乙

甲骨文丙

柄

説文解字》:,位方,萬物成炳然。陰气初起,陽气將虧。从一入一者,陽也。丙承乙,象人肩。凡丙之屬皆从丙。

有人說甲骨文 甲骨文丙 『丙』是『柄』的原字,或許源於石器時代。之後用於『天干』,根據維基百科詞條上說︰

天干最晚在夏朝已經開始,明顯的證據是夏朝後期有帝王叫做孔甲 胤甲。但是正式將這十個符號命名為天干應該與地支有關:干為主幹,支為分支,兩個相對的命名應當是一起出現的。在商朝開始出現天干與地支配和用以紀日,使用干支紀年要更晚一些。

關於天干何來說法眾多,其中一種是古人根據事物十個狀態排序以定的,視為循環。其中植物的生長就是一例︰

  1. 甲就是「鎧甲」,指萬物破殼,植物破土萌芽;
  2. 乙就是「軋」,指萬物初出地面,呈彎曲狀;
  3. 丙指就「炳」,指萬物長勢旺盛;
  4. 丁就是「壯」,指萬物的長勢猶處於青春期,成長壯實;
  5. 戊就是「茂」,指萬物生長最茂盛的時期,是為最頂峰;
  6. 己就是「起」,指植物開始屈曲其形;
  7. 庚就是「更」,指植物枯萎衰亡,始入土中,與乙相反;
  8. 辛就是「新」,指萬物更新;
  9. 壬就是「姙」,指陽氣正潛地中,萬物被養育;
  10. 癸就是「揆」,指萬物閉藏於土,萬物萌芽。

現代研究的結論之一是天干源於原始人類以人體部位計數排序,下面列出《說文解字》中的釋義:

  1. 一曰人頭宐為甲,甲象人頭。
  2. 乙承甲,象人頸。
  3. 丙承乙,象人肩。
  4. 丁承丙,象人心。
  5. 戊承丁,象人肋。
  6. 己承戊,象人腹。
  7. 庚承己,象人齋。
  8. 辛承庚,象人股。
  9. 壬承辛,象人脛。脛,任體也。
  10. 癸承壬,象人足。

試想『石』穿了『孔』添了『柄』,就成了『石斧』,從『工具』的『創新』觀點來看,絕非敲擊的『石器』可以比擬!因為不只 是『敲擊力』的增加,而且更『好用』的吧!!或許中國以『農』立國久矣,有著《易經》說卦講的『乾』為『馬』,『坤』為『牛』之天地『做牛做馬』精神,因此喜歡效法『厚德載物』的『蓋亞』 ,產生『反芻消化』之『中道』『文化』的耶??所以『文化』中可以『彼此貫串』的理念就多,還有眾多的『口訣』,比方說︰

宋代朱熹在《周易本義》中寫了一首《八卦取象歌》幫助人記住八卦的卦象:

乾三連(☰),坤六斷(☷);
震仰盂(☳),艮覆碗(☶);
離中虛(☲),坎中滿(☵);
兌上缺(☱),巽下斷(☴)。

就是一種『學習』的小技巧,『記憶』的聯想法,容易朗朗上口。

─── 摘自《《派生》 Python 作坊【丙】園林景觀

 

既然欲覽 GrovePi 之園林景觀,又已知其韌體

void receiveData(int byteCount)

有『越界』的事實。豈應不先修繕,就隨意斧鑿開墾的耶!因此在繼續探索前, 略作一點『補丁』,同時制定『除錯』啟閉『指令』 ,這也算未來增刪『感測器』時,先將寫程式之章法預演一下。

【 grove_pi_v1_2_5.ino 補丁】

# grove_pi_v1_2_5.ino 第三十三行。
int cmd[5];
int index=0;
int flag=0;
int i;
byte val=0,b[21],float_array[4],dht_b[21];
unsigned char dta[21];
int length;
int aRead=0;
byte accFlag=0,clkFlag=0;
int8_t accv[3];
byte rgb[] = { 0, 0, 0 };
int run_once;
# 增加 debug
int debug = 0;

# 第五百八十九行
        else if(cmd[0]==flow_dis_cmd)
    {
                flow_run_bk=0;
        detachInterrupt(0);
        cmd[0]=0;
    }

# 增加啟閉指令
# 開啟
    else if(cmd[0]==254)
      debug=1;
# 關閉
    else if(cmd[0]==255)
      debug=0;
  }

# 第六百五十六行
       cmd[index++] = Wire.read();
    }
# 出 while 迴圈後,檢查 index
    //cmd buffer index check
    if(index==5)
      index=0;
# 是否要 debug
    if(debug==1)
    {
      Serial.print("CMD = ");
      Serial.print(cmd[0]);
      Serial.print(", ");
      Serial.print("index =  ");
      Serial.println(index);
    }

# 第六百九十一行
  if(cmd[0]==flow_read_cmd)
  {
    Wire.write(flow_val,3);
    flow_val[0]=0;
        cmd[0]=0;
  }
# 是否要 debug
    if(debug==1)
    {
      Serial.print("DATA = ");
      Serial.print(b[0]);
      Serial.print(", ");
      Serial.print(b[1]);
      Serial.print(", ");
      Serial.println(b[2]);
    }
}

 

【 grovepi.py 補丁】

# 第一百五十二行
flow_read_cmd=[12]
flow_disable_cmd=[13]
flow_en_cmd=[18]

# 增加啟閉 debug 指令
en_debug=[254]
dis_debug=[255]

# 第五百五十八行
def flowRead():
        write_i2c_block(address, flow_read_cmd + [unused, unused, unused])
        time.sleep(.2)
        data_back= bus.read_i2c_block_data(address, 1)[0:3]
        #print data_back
        if data_back[0]!=255:
                return [data_back[0],data_back[2]*256+data_back[1]]
        else:
                return [-1,-1]
# 增加開啟除錯
def debugEnable():
        write_i2c_block(address, en_debug + [unused, unused, unused])
        time.sleep(.2)
# 增加關閉除錯
def debugDisable():
        write_i2c_block(address, dis_debug + [unused, unused, unused])
        time.sleep(.2)
#

 

【補丁測試】

※精簡將不再註釋,若有不熟悉者,請閱讀先前文本。

pi@raspberrypi ~/example python 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 >>> addr = 0x05 >>> grovepi.debugEnable() >>> potentiometer = 0 >>> grovepi.pinMode(potentiometer,"INPUT") 1 >>> grovepi.analogRead(potentiometer) 0 [11, 2, 190, 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] 702 >>> ultrasonic_ranger = 2 >>> grovepi.ultrasonicRead(ultrasonic_ranger) 0 [11, 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 >>> grovepi.read_i2c_block(addr) [11, 0, 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, 255] >>> grovepi.read_i2c_block(addr) [11, 0, 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, 255] >>> grovepi.read_i2c_block(addr) [11, 0, 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, 255] >>> grovepi.read_i2c_block(addr) [11, 0, 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, 255] >>> grovepi.read_i2c_block(addr) [11, 0, 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, 255] >>> relay=8 >>> grovepi.pinMode(relay,"OUTPUT") 1 >>> grovepi.digitalWrite(relay,1) 1 >>> grovepi.digitalWrite(relay,0) 1 >>> grovepi.ultrasonicRead(ultrasonic_ranger) 0 [11, 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 >>> led=5 >>> grovepi.pinMode(led,"OUTPUT") 1 >>> grovepi.analogWrite(led,128) 1 >>> grovepi.analogWrite(led,8) 1 >>> grovepi.analogWrite(led,255) 1 >>> power=7 >>> grovepi.pinMode(power,"OUTPUT") 1 >>> grovepi.digitalWrite(power,1) 1 >>> grovepi.digitalWrite(power,0) 1 >>> grovepi.debugDisable() >>> 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 >>> grovepi.analogRead(potentiometer) 0 [0, 2, 189, 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] 701 >>> grovepi.debugEnable() >>> grovepi.analogWrite(led,128) 1 >>> grovepi.analogWrite(led,8) 1 >>> grovepi.analogRead(potentiometer) 0 [11, 2, 190, 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] 702 >>>  </pre>   <pre class="lang:sh decode:true">pi@raspberrypi ~ stty -F /dev/ttyUSB0 115200
pi@raspberrypi ~ $ cat /dev/ttyUSB0 
CMD = 5, index =  4

CMD = 3, index =  4

DATA = 0, 2, 190

CMD = 3, index =  0

CMD = 7, index =  4

DATA = 0, 0, 198

CMD = 7, index =  0

CMD = 1, index =  1

CMD = 1, index =  2

CMD = 1, index =  3

CMD = 1, index =  4

CMD = 1, index =  0

CMD = 5, index =  4

CMD = 2, index =  4

CMD = 2, index =  4

CMD = 7, index =  4

DATA = 0, 0, 198

CMD = 7, index =  0

CMD = 5, index =  4

CMD = 4, index =  4

CMD = 4, index =  4

CMD = 4, index =  4

CMD = 5, index =  4

CMD = 2, index =  4

CMD = 2, index =  4

CMD = 255, index =  4

CMD = 4, index =  4

CMD = 4, index =  4

CMD = 3, index =  4

DATA = 0, 2, 190

CMD = 3, index =  0

#

 

 

 

 

 

 

 

 

 

 

 

 

 

W!o+ 的《小伶鼬工坊演義》︰ 一窺全豹之系統設計‧探索‧甲

甲骨文甲

金文甲

甲骨文乙

《說文解字》:甲,東方之孟,陽气萌動,从木戴孚甲之象。一曰人頭宐【宜】為甲,甲象人頭。凡甲之屬皆从甲。金文甲,古文甲,始於十,見於千,成於木之象。

《說文解字》:乙,象春艸木冤曲而出,陰气尚彊,其出乙乙也。與丨同意。乙承甲,象人頸。凡乙之屬皆从乙。

─── 見於《《派生》 Python 作坊【乙】選址定基

莊子‧《天地》篇中︰

子貢南遊於楚,反於晉,過漢陰,見一丈人方將為圃畦,鑿隧而入井,抱甕而出灌,搰搰然用力甚多而見功寡。

子貢曰:「有械於此,一日浸百畦,用力甚寡而見功多,夫子不欲乎?」

為圃者卬而視之曰:「柰何?」曰:「鑿木為機,後重前輕,挈手若抽,數如泆湯,其名為槔。」

為圃者忿然作色而笑曰:「吾聞之吾師,機械者必有機事,有機事者必有機心。機心存於胸中,則純白不備;純白不備,則神生不定;神生不定者,道之所不載也。吾非不知,羞而不為也。

子貢瞞然慚,俯而不對。有閒,為圃者曰:「子奚為者邪?」

曰:「孔丘之徒也。」

為圃者曰:「子非夫博學以擬聖,於于以蓋眾,獨弦哀歌以賣名聲於天下者乎?汝方將忘汝神氣,墮汝形骸,而庶幾乎!而身之不能治,而何暇治天下乎!子往矣,無乏吾事!」

子貢卑陬失色,頊頊然不自得,行三十里而後愈。

……

,談及『機械』、『機事』、『機心』;終歸之於『神』,但求其『定』,為何也?但思『取捨』一事依賴『價值』,『價值』一事存於『信念』,與其『一改再改』?莫若『定』耶!!況且《大學 》裡有言︰『定』、『靜』、『安』、『慮』、『得』的也。因此假使『人』不法以『地』的『定』與『靜』,又怎麼能免於『安』和『慮』之『無常』呢?當真可『得』之『於天』的嘛??

如果『天』『失時』且『地』『失候』,所謂

龍抬頭

龍頭節,又稱「龍抬頭」或「春龍節」,節日日期為陰曆二月初二,是中國的傳統節日之一。根據民間傳說,此為主管雲雨的龍王抬頭之日,也意謂著在此之後水會漸多。也有人認為「龍抬頭」指的是百蟲開始於初春甦醒:如俗話說「二月二,龍抬頭,蠍子、蜈蚣都露頭。」

相關傳說

二月初二,龍抬頭,相傳二月初二是軒轅黃帝出生的日子。夏曆二月初二,傳說天上掌管降雨之神龍王抬頭。意味今後雨水就會多了起來,有利於耕種。一種說法是龍王因思念失去的女兒,因此總是在農曆二月初二這天從海底抬頭出來,望著失去女兒的方向,以寄思念。

,又該是『何月』與『何日』的哩!!

此所以列之於茲,實乃因□○『所好』

吉多·范羅蘇姆 Guido van Rossum 先生喜歡看『蒙提·派森的飛行馬戲團』── Monty Python’s Flying Circus,所以把他創始的程式語言叫做 『 Python 』 。Python 巨蟒,《爾雅·釋魚》蟒,王蛇。又《註》蟒,蛇最大者,故曰王蛇。正是『小王子』一書上所說的︰

吞了象,看起來像帽子的那個。

吉多的 Python 『非同』於其他程式語言,居然把『空白』符號寫進了它的『文法』裡,竟然用『對齊的空白』表示程式區塊。如是種種『見地』,匯聚成一條稱作『非同的』pythonic  Way 大道。吉多他的『中心思想』,集中的表現在由 Tim Peters 先生所寫的『 Python 的禪』,收錄在『 this模組 module 裡︰

import this

The Zen of Python, by Tim Peters

Beautiful is better than ugly.
美比醜好

Explicit is better than implicit.
明白比晦暗好

Simple is better than complex.
簡單比複雜好

Complex is better than complicated.
複雜比複雜化好

……

─── 見於《『騛罿』── 非同的禪!!

,無關『思辯』尚且不宜作『思辨』之故。於是祇談『實事求是』之『事』,卻也不能不說及『批判論』

Criticism

Criticism is the practice of judging the merits and faults of something.

Criticism as an evaluative or corrective exercise can occur in any area of human life. Criticism can therefore take many different forms (see below). How exactly people go about criticizing, can vary a great deal. In specific areas of human endeavour, the form of criticism can be highly specialized and technical; it often requires professional knowledge to understand the criticism. This article provides only general information about criticism. For subject-specific information, see the Varieties of criticism page.

To criticize does not necessarily imply “to find fault”, but the word is often taken to mean the simple expression of an objection against prejudice, or a disapproval of something. Often criticism involves active disagreement, but it may only mean “taking sides”. It could just be an exploration of the different sides of an issue. Fighting is not necessarily involved.

Criticism is often presented as something unpleasant, but it need not be. It could be friendly criticism, amicably discussed, and some people find great pleasure in criticism (“keeping people sharp”, “providing the critical edge”). The Pulitzer Prize for Criticism has been presented since 1970 to a newspaper writer who has demonstrated ‘distinguished criticism’.

Normally criticism involves a dialogue of some kind, direct or indirect, and in that sense criticism is an intrinsically social activity. Even if one is only criticizing a book or an idea in private, it is usually assumed there is someone who will be made aware of the criticism being expressed at some point, although who exactly will hear it, may also remain unknown. One is still engaging with the ideas of others, even if only indirectly. One can of course also keep a criticism to oneself, rather than express or communicate it, but in general the intention is, that someone else ought to be aware of it, however that may occur. Self-criticism, even if wholly private, still mentally takes the concerns of others into account.

Another meaning of criticism is the study, evaluation, and interpretation of literature, artwork, film, and social trends (see the article links below). The goal of this type of criticism is to understand the possible meanings of cultural phenomena, and the context in which they take shape. In so doing, the attempt is often made to evaluate how cultural productions relate to other cultural productions, and what their place is within a particular genre, or a particular cultural tradition.

……

之『★★』的『論難』也。所以這裡僅先列出『修改』、『測試』之事,再做『討論』耶??!!

pi@raspberrypi ~/example python 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 >>> addr = 0x05  # 不觸動韌體『 receiveData 』, Wire 傳回 0  >>> grovepi.read_i2c_byte(addr) 0 # 觸動韌體『 receiveData 』, SMBus 讀回 32 byte 。注意第二 Byte 亦為 0 。這或許是 GrovePi 的回傳緩衝器 buffer 始於一之故。 由於會改變 index ,恐有『越界』之虞。 >>> grovepi.read_i2c_block(addr) [11, 0, 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, 255] # Grove - Rotary Angle Sensor 測試 >>> potentiometer = 0 >>> sensor_value = grovepi.analogRead(potentiometer) 0 [11, 2, 190, 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 702 # 注意。注意。這造成 cmd[5] array 指標『越界』。 >>> grovepi.read_i2c_block(addr) [11, 0, 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, 255] # 無須設定 Grove - Rotary Angle Sensor 為『輸入』? >>> grovepi.pinMode(potentiometer,"INPUT") 1 # Ultrasonic sensor 接於『二』測試。已將//attachInterrupt(0,readPulseDust,CHANGE); 『刪除』。 請注意多次讀取值。 >>> ultrasonic_ranger = 2 >>> grovepi.ultrasonicRead(ultrasonic_ranger) 0 [11, 1, 196, 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]  452 # Relay 接於『八』測試 >>> relay = 8 # 一定要宣告 pinMode 為『輸出』 >>> grovepi.pinMode(relay,"OUTPUT") 1 # relay 開 >>> grovepi.digitalWrite(relay,1) 1 # relay 關 >>> grovepi.digitalWrite(relay,0) 1 # 與 relay 沒有交互影響。注意讀取值與之前不同 >>> grovepi.ultrasonicRead(ultrasonic_ranger) 0 [11, 0, 199, 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] 199 # 注意指標『越界』 >>> grovepi.read_i2c_block(addr) [11, 0, 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, 255] # 注意指標『變化』 >>> grovepi.digitalWrite(relay,1) 1 # 穩定性測試 >>> grovepi.analogRead(potentiometer) 0 [11, 2, 190, 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]  702 >>>  </pre>   <pre class="lang:default decode:true">pi@raspberrypi ~ stty -F /dev/ttyUSB0 115200
pi@raspberrypi ~ $ cat /dev/ttyUSB0
CMD = 1, index =  1

CMD = 3, index =  4

CMD = 3, index =  5

# 越界
CMD = 3, index =  6

CMD = 5, index =  4

CMD = 7, index =  4

CMD = 7, index =  5

CMD = 5, index =  4

CMD = 2, index =  4

CMD = 2, index =  4

CMD = 7, index =  4

CMD = 7, index =  5

# 越界
CMD = 7, index =  6

CMD = 2, index =  4

CMD = 3, index =  4

CMD = 3, index =  5

 

void setup()
{
# 設定最高速之 115200 buad
    Serial.begin(115200);         // start serial for output
    Wire.begin(SLAVE_ADDRESS);

    Wire.onReceive(receiveData);
    Wire.onRequest(sendData);

# 二、八問題的主因
        //attachInterrupt(0,readPulseDust,CHANGE);
}

void receiveData(int byteCount)
{
    while(Wire.available())
    {
      if(Wire.available()==4)
      {
        flag=0;
        index=0;
                run_once=1;
      }
        cmd[index++] = Wire.read();
    }
# 序列埠『監督』輸出
    Serial.print("CMD = ");
    Serial.print(cmd[0]);
    Serial.print(", ");
    Serial.print("index =  ");
    Serial.println(index);
}


void readPulseDust()
{
  t = millis();
# 用『二』當作『插斷』 INT0 輸入
  l_status = digitalRead(2);  // Represents if the line is low or high.
  if(l_status)
  {
# 不知為何固定用『八』?
         digitalWrite(8,0);
    // If the line is high (1), the pulse just ended
    pulse_end = t;
  }
  else
  {   // If the line is low (0), the pulse just started
    pulse_start = t;
# 二、八現象之來源
        digitalWrite(8,1);
  }

  if(pulse_end > pulse_start)
  {
    duration = pulse_end - pulse_start;
    lowpulseoccupancy = lowpulseoccupancy+duration;   // Add to the pulse length.
    pulse_end = 0;    // If you don't reset this, you'll keep adding the pulse length over and over.
  }
}


 

 

 

 

 

 

 

 

 

 

 

 

 

W!o+ 的《小伶鼬工坊演義》︰ 一窺全豹之系統設計‧探索開始

W!o+ 認為一個『實驗』的『結束』,也只是『探索』之『開始』。或許舊的疑惑未解!新的疑惑又生!!因此『分析』結果,『整理 』資料 ,『思辨』要點,『綜合』通盤 …… ,『準備』下次『實驗 』計畫 ,正是『科學求知』的方法。………

固然總有『不知』的時候?總有『不能』的情況??此時恰好困知勉行乎!也許終有『知之』的一天吧!?

之前的實驗結果,一起頭就叫人訝異︰

# 關閉電源,重新開機。確定 Arduino 在 Hard Reset 狀態。
pi@raspberrypi ~/example $ python
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
>>> addr = 0x05

# 韌體 Wire 程式庫,如何處理『未下指令』之 I2C 『讀取』

# 位元組讀取
>>> grovepi.read_i2c_byte(addr)
0
# 區塊讀取
>>> grovepi.read_i2c_block(addr)
[11, 0, 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, 255]
# 長度 32 ?
>>> len(grovepi.read_i2c_block(addr))
32

# Grove – Rotary Angle Sensor 測試。命令 3
>>> potentiometer = 0
# 設定 pinMode 為輸入。命令 5
>>> grovepi.pinMode(potentiometer,"INPUT")
1
# 讀取值
>>> sensor_value = grovepi.analogRead(potentiometer)
0
[11, 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
………

 

。就讓我們從此處展開探索之旅耶!!

先匯總『問題』如下︰

‧ 為什麼『未下指令』,還能無誤讀取?

‧ 為什麼『位元組讀取』,傳回值為 0 ?

‧ 為什麼『區塊讀取』,傳回長度是 32 ?

‧ 為什麼『Grove – Rotary Angle Sensor』測試,序列埠沒有輸出?

‧………

 

經過多次查詢以及閱讀,『整理』與之相關資料如下︰

☆【 ATmega CPU DataSheet 】

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

第二零六頁

22. 2-wire Serial Interface
22.1 Features
‧ Simple Yet Powerful and Flexible Communication Interface, only ‧ ‧ ‧ ‧ two Bus Lines Needed
‧ Both Master and Slave Operation Supported
‧ Device can Operate as Transmitter or Receiver
‧ 7-bit Address Space Allows up to 128 Different Slave Addresses
‧ Multi-master Arbitration Support
‧ Up to 400kHz Data Transfer Speed
‧ Slew-rate Limited Output Drivers
‧ Noise Suppression Circuitry Rejects Spikes on Bus Lines
‧ Fully Programmable Slave Address with General Call Support
‧ Address Recognition Causes Wake-up When AVR is in Sleep Mode
‧ Compatible with Philips’ I2C protocol

……

從屬接收模式

Atmegas328p-I2C-Slave-Receiver-Mode

 

從屬傳送模式

Atmegas328p-I2C-Slave-Transmitter-Mode

 

☆ pi@raspberrypi /usr/share/arduino/libraries/Wire/utility $ ls
twi.c twi.h
pi@raspberrypi /usr/share/arduino/libraries/Wire/utility $ pwd
/usr/share/arduino/libraries/Wire/utility

 

/*
 twi.c - TWI/I2C library for Wiring & Arduino
 Copyright (c) 2006 Nicholas Zambetti. All right reserved.

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

 Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts
*/



   // Slave Receiver
    case TW_SR_SLA_ACK:   // addressed, returned ack
    case TW_SR_GCALL_ACK: // addressed generally, returned ack
    case TW_SR_ARB_LOST_SLA_ACK:   // lost arbitration, returned ack
    case TW_SR_ARB_LOST_GCALL_ACK: // lost arbitration, returned ack
      // enter slave receiver mode
      twi_state = TWI_SRX;
      // indicate that rx buffer can be overwritten and ack
      twi_rxBufferIndex = 0;
      twi_reply(1);
      break;
    case TW_SR_DATA_ACK:       // data received, returned ack
    case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack
      // if there is still room in the rx buffer
      if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){
        // put byte in buffer and ack
        twi_rxBuffer[twi_rxBufferIndex++] = TWDR;
        twi_reply(1);
      }else{
        // otherwise nack
        twi_reply(0);
      }
      break;
    case TW_SR_STOP: // stop or repeated start condition received
      // put a null char after data if there's room
      if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){
        twi_rxBuffer[twi_rxBufferIndex] = '\0';
      }
      // sends ack and stops interface for clock stretching
      twi_stop();
# 重點
      // callback to user defined callback
      twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex);
      // since we submit rx buffer to "wire" library, we can reset it
      twi_rxBufferIndex = 0;
      // ack future responses and leave slave receiver state
      twi_releaseBus();
      break;
    case TW_SR_DATA_NACK:       // data received, returned nack
    case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack
      // nack back at master
      twi_reply(0);
      break;


    // Slave Transmitter
    case TW_ST_SLA_ACK:          // addressed, returned ack
    case TW_ST_ARB_LOST_SLA_ACK: // arbitration lost, returned ack
      // enter slave transmitter mode
      twi_state = TWI_STX;
      // ready the tx buffer index for iteration
      twi_txBufferIndex = 0;
      // set tx buffer length to be zero, to verify if user changes it
      twi_txBufferLength = 0;
      // request for txBuffer to be filled and length to be set
# 重點
      // note: user must call twi_transmit(bytes, length) to do this
      twi_onSlaveTransmit();

# 要點
      // if they didn't change buffer & length, initialize it
      if(0 == twi_txBufferLength){
        twi_txBufferLength = 1;
        twi_txBuffer[0] = 0x00;
      }
      // transmit first byte from buffer, fall
    case TW_ST_DATA_ACK: // byte sent, ack returned
      // copy data to output register
      TWDR = twi_txBuffer[twi_txBufferIndex++];
      // if there is more to send, ack, otherwise nack
      if(twi_txBufferIndex < twi_txBufferLength){
        twi_reply(1);
      }else{
        twi_reply(0);
      }
      break;



/* 
 * Function twi_attachSlaveRxEvent
 * Desc sets function called before a slave read operation
 * Input function: callback function to use
 * Output none
 */
void twi_attachSlaveRxEvent( void (*function)(uint8_t*, int) )
{
 twi_onSlaveReceive = function;
}

/* 
 * Function twi_attachSlaveTxEvent
 * Desc sets function called before a slave write operation
 * Input function: callback function to use
 * Output none
 */
void twi_attachSlaveTxEvent( void (*function)(void) )
{
 twi_onSlaveTransmit = function;
}

 

☆ 【 Arduino Wire 程式庫】深度闡釋

:: Wire Library, Explored

An indepth reference to the Arduino Wire library.

 

☆ 『 Linux/Documentation/i2c/smbus-protocol

I2C Block Transactions
======================

The following I2C block transactions are supported by the SMBus layer and are described here for completeness. They are *NOT* defined by the SMBus specification.

I2C block transactions do not limit the number of bytes transferred but the SMBus layer places a limit of 32 bytes.

I2C Block Read: i2c_smbus_read_i2c_block_data()
================================================

This command reads a block of bytes from a device, from a designated register that is specified through the Comm byte.

S Addr Wr [A] Comm [A]
S Addr Rd [A] [Data] A [Data] A … A [Data] NA P

Functionality flag: I2C_FUNC_SMBUS_READ_I2C_BLOCK

I2C Block Write: i2c_smbus_write_i2c_block_data()
==================================================

The opposite of the Block Read command, this writes bytes to a device, to a designated register that is specified through the Comm byte. Note that command lengths of 0, 2, or more bytes are supported as they are indistinguishable from data.

S Addr Wr [A] Comm [A] Data [A] Data [A] … [A] Data [A] P

Functionality flag: I2C_FUNC_SMBUS_WRITE_I2C_BLOCK

 

☆ 『 i2c-tools_3.1.0.orig.tar.bz2

/*
 * smbusmodule.c - Python bindings for Linux SMBus access through i2c-dev
 * Copyright (C) 2005-2007 Mark M. Hoffman <mhoffman@lightlink.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */


PyDoc_STRVAR(SMBus_read_i2c_block_data_doc,
 "read_i2c_block_data(addr, cmd, len=32) -> results\n\n"
 "Perform I2C Block Read transaction.\n");

static PyObject *
SMBus_read_i2c_block_data(SMBus *self, PyObject *args)
{
# 要點
 int addr, cmd, len=32;
 union i2c_smbus_data data;

 if (!PyArg_ParseTuple(args, "ii|i:read_i2c_block_data", &addr, &cmd,
 &len))
 return NULL;

 SMBus_SET_ADDR(self, addr);

 data.block[0] = len;
 /* save a bit of code by calling the access function directly */
 if (i2c_smbus_access(self->fd, I2C_SMBUS_READ, (__u8)cmd,
 len == 32 ? I2C_SMBUS_I2C_BLOCK_BROKEN:
 I2C_SMBUS_I2C_BLOCK_DATA, &data)) {
 PyErr_SetFromErrno(PyExc_IOError);
 return NULL;
 }

 /* first byte of the block contains (remaining) data length */
 return SMBus_buf_to_list(&data.block[1], data.block[0]);
}

PyDoc_STRVAR(SMBus_write_i2c_block_data_doc,
 "write_i2c_block_data(addr, cmd, [vals])\n\n"
 "Perform I2C Block Write transaction.\n");

static PyObject *
SMBus_write_i2c_block_data(SMBus *self, PyObject *args)
{
 int addr, cmd;
 union i2c_smbus_data data;

 if (!PyArg_ParseTuple(args, "iiO&:write_i2c_block_data", &addr, &cmd,
 SMBus_list_to_data, &data))
 return NULL;

 SMBus_SET_ADDR(self, addr);

 /* save a bit of code by calling the access function directly */
 if (i2c_smbus_access(self->fd, I2C_SMBUS_WRITE, (__u8)cmd,
 I2C_SMBUS_I2C_BLOCK_BROKEN, &data)) {
 PyErr_SetFromErrno(PyExc_IOError);
 return NULL;
 }

 Py_INCREF(Py_None);
 return Py_None;
}

 

同時也參考他人之討論︰

☆ 『  [I2C] onRequest and onReceive as slave with Raspberry Pi Master

Sep 10, 2013, 06:39 pmLast Edit: Sep 10, 2013, 06:57 pm by brainvoid Reason: 1
 
Hey guys,
I discovered a big Problem for my Project today. I try to connect a few Arduinos to a Raspberry Pi with I2C. I have a onRequest and a onReceive function (code below). On my Raspberry Pi I use smbus with python.My onReceive function works fine and well, every “bus.write[…]” function calls my onReceive function as it should.
But not onRequest. Only when i call “read_byte(addr)” in my python script, the Arduino will call the onRequest function. But it is necessary that I can use at least “byte read_byte_data(addr,cmd)” or “long[] read_block_data(addr,cmd)”. These functions call the onReceive Method, whyever.So I thought “no Problem”, just use onReceive like onRequest and write data there. But then the BUS is corrupted and the Python on Raspberry Pi gets an I/O Error.I just recognized that with the command “print bus.read_i2c_block_data(0x04, 0x01)” it prints nearly the right output (take a look in my log below), but on my Arduino Serial connection the “dataRequest() called with command” is not printed. I just don’t understand o_OI don’t know what I’m doing wrong o_O. Can someone explain this?Best regards
brainvoid

───

 

請判斷,這是否足以『回答』上述『問題』?能夠『準備』新實驗『計劃』的呢??