質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

Q&A

解決済

2回答

670閲覧

Grove シリアルカメラについて

kyousukelin

総合スコア30

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

0グッド

0クリップ

投稿2017/09/07 06:56

Grove シリアルカメラをArduinoを使って動かしたいのですが、プログラムを実行した結果、次のエラーが出てきました。これはどういう意味なのでしょうか?

プログラムコード

// File SerialCamera_DemoCode_CJ-OV528.ino // 8/8/2013 Jack Shao // Demo code for using seeeduino or Arduino board to cature jpg format // picture from seeed serial camera and save it into sd card. Push the // button to take the a picture . // For more details about the product please check http://www.seeedstudio.com/depot/ #include <SPI.h> #include <arduino.h> #include <SD.h> #define PIC_PKT_LEN 128 //data length of each read, dont set this too big because ram is limited #define PIC_FMT_VGA 7 #define PIC_FMT_CIF 5 #define PIC_FMT_OCIF 3 #define CAM_ADDR 0 #define CAM_SERIAL Serial #define PIC_FMT PIC_FMT_VGA File myFile; const byte cameraAddr = (CAM_ADDR << 5); // addr const int buttonPin = 8; // the number of the pushbutton pin unsigned long picTotalLen = 0; // picture length int picNameNum = 0; /*********************************************************************/ void setup() { Serial.begin(9600); pinMode(buttonPin, INPUT); // initialize the pushbutton pin as an input Serial.println("Initializing SD card...."); pinMode(10,OUTPUT); // CS pin of SD Card Shield if (!SD.begin(10)) { Serial.print("sd init failed"); return; } Serial.println("sd init done."); initialize(); } /*********************************************************************/ void loop() { int n = 0; while(1){ Serial.println("\r\nPress the button to take a picture"); while (digitalRead(buttonPin) == LOW); //wait for buttonPin status to HIGH if(digitalRead(buttonPin) == HIGH){ delay(20); //Debounce if (digitalRead(buttonPin) == HIGH) { Serial.println("\r\nbegin to take picture"); delay(200); if (n == 0) preCapture(); Capture(); GetData(); } Serial.print("\r\nTaking pictures success ,number : "); Serial.println(n); n++ ; } } } /*********************************************************************/ void clearRxBuf() { while (Serial.available()) { Serial.read(); } } /*********************************************************************/ void sendCmd(char cmd[], int cmd_len) { for (char i = 0; i < cmd_len; i++) Serial.print(cmd[i]); } /*********************************************************************/ void initialize() { char cmd[] = {0xaa,0x0d|cameraAddr,0x00,0x00,0x00,0x00} ; unsigned char resp[6]; Serial.setTimeout(500); while (1) { //clearRxBuf(); sendCmd(cmd,6); if (Serial.readBytes((char *)resp, 6) != 6) { continue; } if (resp[0] == 0xaa && resp[1] == (0x0e | cameraAddr) && resp[2] == 0x0d && resp[4] == 0 && resp[5] == 0) { if (Serial.readBytes((char *)resp, 6) != 6) continue; if (resp[0] == 0xaa && resp[1] == (0x0d | cameraAddr) && resp[2] == 0 && resp[3] == 0 && resp[4] == 0 && resp[5] == 0) break; } } cmd[1] = 0x0e | cameraAddr; cmd[2] = 0x0d; sendCmd(cmd, 6); Serial.println("\nCamera initialization done."); } /*********************************************************************/ void preCapture() { char cmd[] = { 0xaa, 0x01 | cameraAddr, 0x00, 0x07, 0x00, PIC_FMT }; unsigned char resp[6]; Serial.setTimeout(100); while (1) { clearRxBuf(); sendCmd(cmd, 6); if (Serial.readBytes((char *)resp, 6) != 6) continue; if (resp[0] == 0xaa && resp[1] == (0x0e | cameraAddr) && resp[2] == 0x01 && resp[4] == 0 && resp[5] == 0) break; } } void Capture() { char cmd[] = { 0xaa, 0x06 | cameraAddr, 0x08, PIC_PKT_LEN & 0xff, (PIC_PKT_LEN>>8) & 0xff ,0}; unsigned char resp[6]; Serial.setTimeout(100); while (1) { clearRxBuf(); sendCmd(cmd, 6); if (Serial.readBytes((char *)resp, 6) != 6) continue; if (resp[0] == 0xaa && resp[1] == (0x0e | cameraAddr) && resp[2] == 0x06 && resp[4] == 0 && resp[5] == 0) break; } cmd[1] = 0x05 | cameraAddr; cmd[2] = 0; cmd[3] = 0; cmd[4] = 0; cmd[5] = 0; while (1) { clearRxBuf(); sendCmd(cmd, 6); if (Serial.readBytes((char *)resp, 6) != 6) continue; if (resp[0] == 0xaa && resp[1] == (0x0e | cameraAddr) && resp[2] == 0x05 && resp[4] == 0 && resp[5] == 0) break; } cmd[1] = 0x04 | cameraAddr; cmd[2] = 0x1; while (1) { clearRxBuf(); sendCmd(cmd, 6); if (Serial.readBytes((char *)resp, 6) != 6) continue; if (resp[0] == 0xaa && resp[1] == (0x0e | cameraAddr) && resp[2] == 0x04 && resp[4] == 0 && resp[5] == 0) { Serial.setTimeout(1000); if (Serial.readBytes((char *)resp, 6) != 6) { continue; } if (resp[0] == 0xaa && resp[1] == (0x0a | cameraAddr) && resp[2] == 0x01) { picTotalLen = (resp[3]) | (resp[4] << 8) | (resp[5] << 16); Serial.print("picTotalLen:"); Serial.println(picTotalLen); break; } } } } /*********************************************************************/ void GetData() { unsigned int pktCnt = (picTotalLen) / (PIC_PKT_LEN - 6); if ((picTotalLen % (PIC_PKT_LEN-6)) != 0) pktCnt += 1; char cmd[] = { 0xaa, 0x0e | cameraAddr, 0x00, 0x00, 0x00, 0x00 }; unsigned char pkt[PIC_PKT_LEN]; char picName[] = "pic00.jpg"; picName[3] = picNameNum/10 + '0'; picName[4] = picNameNum%10 + '0'; if (SD.exists(picName)) { SD.remove(picName); } myFile = SD.open(picName, FILE_WRITE); if(!myFile){ Serial.println("myFile open fail..."); } else{ Serial.setTimeout(1000); for (unsigned int i = 0; i < pktCnt; i++) { cmd[4] = i & 0xff; cmd[5] = (i >> 8) & 0xff; int retry_cnt = 0; retry: delay(10); clearRxBuf(); sendCmd(cmd, 6); uint16_t cnt = Serial.readBytes((char *)pkt, PIC_PKT_LEN); unsigned char sum = 0; for (int y = 0; y < cnt - 2; y++) { sum += pkt[y]; } if (sum != pkt[cnt-2]) { if (++retry_cnt < 100) goto retry; else break; } myFile.write((const uint8_t *)&pkt[4], cnt-6); //if (cnt != PIC_PKT_LEN) break; } cmd[4] = 0xf0; cmd[5] = 0xf0; sendCmd(cmd, 6); } myFile.close(); picNameNum ++; }

エラー文

C:\Users\PCUser\Desktop\arduino-1.8.2\菴懊▲縺溘d縺、\sketch_sep07a\sketch_sep07a.ino: In function 'void initialize()': C:\Users\PCUser\Desktop\arduino-1.8.2\菴懊▲縺溘d縺、\sketch_sep07a\sketch_sep07a.ino:83:59: warning: narrowing conversion of '170' from 'int' to 'char' inside { } [-Wnarrowing] C:\Users\PCUser\Desktop\arduino-1.8.2\菴懊▲縺溘d縺、\sketch_sep07a\sketch_sep07a.ino: In function 'void preCapture()': C:\Users\PCUser\Desktop\arduino-1.8.2\菴懊▲縺溘d縺、\sketch_sep07a\sketch_sep07a.ino:109:71: warning: narrowing conversion of '170' from 'int' to 'char' inside { } [-Wnarrowing] C:\Users\PCUser\Desktop\arduino-1.8.2\菴懊▲縺溘d縺、\sketch_sep07a\sketch_sep07a.ino: In function 'void Capture()': C:\Users\PCUser\Desktop\arduino-1.8.2\菴懊▲縺溘d縺、\sketch_sep07a\sketch_sep07a.ino:123:97: warning: narrowing conversion of '170' from 'int' to 'char' inside { } [-Wnarrowing] C:\Users\PCUser\Desktop\arduino-1.8.2\菴懊▲縺溘d縺、\sketch_sep07a\sketch_sep07a.ino:123:97: warning: narrowing conversion of '128' from 'int' to 'char' inside { } [-Wnarrowing] C:\Users\PCUser\Desktop\arduino-1.8.2\菴懊▲縺溘d縺、\sketch_sep07a\sketch_sep07a.ino:162:72: warning: left shift count >= width of type C:\Users\PCUser\Desktop\arduino-1.8.2\菴懊▲縺溘d縺、\sketch_sep07a\sketch_sep07a.ino: In function 'void GetData()': C:\Users\PCUser\Desktop\arduino-1.8.2\菴懊▲縺溘d縺、\sketch_sep07a\sketch_sep07a.ino:177:68: warning: narrowing conversion of '170' from 'int' to 'char' inside { } [-Wnarrowing]

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

気になる点:

  1. Serial通信の使い方

シリアルカメラはArduinoのシリアル通信端子に接続されていて、シリアル通信を使ってArduinoから指示("撮影せよ"等のコマンド)を送り、カメラから映像データを受け取るというのが、システムの基本的な構成だと思います。

ところが、質問のコードではメッセージの出力にもシリアル通信を使っています。

Serial.print("picTotalLen:"); Serial.println(picTotalLen);

メッセージ出力にはソフトウェアシリアルを使い、カメラとのやりとりのためだけにシリアル通信を使う、というように使い分けるようにしてください。
カメラは、特定のフォーマットで送られるコマンドにしか対処できません。それ以外のデータ(例えば"picTotalLen:")をカメラに送るとカメラが想定外の動作をする恐れがあります。

  1. ビットシフト操作

エラーメッセージにも"left shift count >= width of type"とあるように、データの大きさ(ビット桁数)を無視した箇所が散見されます。
例えば、以下のコード断片では、unsigned char(8ビット)の配列変数 respの要素に対して、8ビットとか、16ビットの左シフトをしています。8ビットしかないデータを8ビット以上左シフトすれば、元の値に関わらず00000000になってしまいます。

void Capture() { char cmd[] = { 0xaa, 0x06 | cameraAddr, 0x08, PIC_PKT_LEN & 0xff, (PIC_PKT_LEN>>8) & 0xff ,0}; unsigned char resp[6]; /* コードをごっそり省略 */ if (resp[0] == 0xaa && resp[1] == (0x0a | cameraAddr) && resp[2] == 0x01) { picTotalLen = (resp[3]) | (resp[4] << 8) | (resp[5] << 16); /* コードを省略 */ } } }
  1. とりあえず無視してよいWarning

"narrowing conversion of '170' from 'int' to 'char'"という警告(Warning)がありますが、これは下のコードのように「char変数に整数を代入している大丈夫?」

cmd[5] = 0xf0;

=== 2)ビットシフト操作 に関して、補足

picTotalLen = (resp[3]) | (resp[4] << 8) | (resp[5] << 16);

は、picTotalLenをInt(32ビットの整数)の、下から8ビットはresp[3]の8ビットと同じ、下から9ビット目から16ビット目はresp[4]の8ビットと同じ、下から17ビット目から24ビット目はresp[5]の8ビットと同じであるようにしたいという事だと思います。
例えば、resp[3]=0x56、resp[4]=0x34、resp[5]=0x12だとすると、picTotalLen=0x123456にしたいのだと推測されます。

この推測が正しいとして、元のコードのように8ビットの値を8桁以上シフトしたら値は0になりますから、8桁シフトしても値がなくならない(十分なビット数がある)値であるIntのデータであるpitTotalLenをシフトするようにします。

コードは以下のようになります。(各行の右側のコメントで、何をしているか説明しています)

picTotalLen = resp[5]; // resp[3]~resp[5]の値が上に揚げた例えのとおりだとすると、picTotalLen=0x12になる。この時点では1-8ビット目だが、後でシフトされた17-24ビット目の値になる picTotalLen = picTotalLen << 8; // 左に8ビットシフトするとpicTotalLen=0x1200になる。 picTotalLen = picTotalLen | resp[4] // 1-8ビット目にresp[4]の値を入れる(元が0なので、OR演算することでresp[4]と同じ値になります)と、picTotalLen = 0x1234になる。 picTotalLen = picTotalLen << 8; // 左に8ビットシフトするとpicTotalLen=0x123400になる。 PicTotalLen = picTotalLen | resp[3] // 1-8ビット目にresp[3]の値を入れると、picTotalLen=0x123456になる。

投稿2017/09/08 05:56

編集2017/09/21 05:55
coco_bauer

総合スコア6915

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kyousukelin

2017/09/09 11:31

回答ありがとうございます。 2)のビットシフト操作についてなのですが、8や16の値をいくつに変えればよいかわかりますでしょうか?
guest

0

ベストアンサー

まず提示されたソースをデフォルトでコンパイルして同じエラー(ワーニング)を確認できました。(本当に文字化けスタイル)
内容の説明としては、まず

arduino

1initialize()関数の中で、

定数'0xaa'つまり10進数で170が元々はint型ですがchar型に変換しております。(警告)
などの警告ばかり。
コンパイル結果を見ても正常な結果を得られています。

ただ、arduinoコンパイラには癖が有ったので一部を以下のようにすると解決の糸口が。

arduino

1 char cmd[6]; 2// = {(char)0xaa,0x0d|cameraAddr,0x00,0x00,0x00,0x00} ; 3 unsigned char resp[6]; 4 cmd[0] = 0xaa; 5 cmd[1] = 0x0d | cameraAddr; 6 cmd[2] = 0x00; 7 cmd[3] = 0x00; 8 cmd[4] = 0x00; 9 cmd[5] = 0x00; 10

これはコンパイラの展開の関係で’cameraAddr'が元々’0’ですが、シフトしたりの計算を必要として、そこまで偉くないコンパイラがワーニングを。
なので毎回通る所と考えファンクションの処理の中に移動。
その他の箇所も同様な原因と考えられるのでこれらを修正してコンパイルをお勧めします。

投稿2017/09/07 10:11

MasahikoHirata

総合スコア3747

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kyousukelin

2017/09/09 11:29

回答ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問