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

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

ただいまの
回答率

90.48%

  • Arduino

    551questions

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

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

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 826

kyousukelin

score 21

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]
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

0

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

initialize()関数の中で、


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

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

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


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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/09 20:29

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

    キャンセル

0

気になる点:

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

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

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

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

2) ビットシフト操作
エラーメッセージにも"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);

/* コードを省略 */      }
    }

}

3) とりあえず無視してよい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/09 20:31

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

    キャンセル

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

  • ただいまの回答率 90.48%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Arduino

    551questions

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