2014年10月30日木曜日

Arduino で遊ぼう(7) static constは、、、

Arduinoはstatic const で宣言してもramを使うことを初めて知った!
http://www.cloverfield.jp/2014/05/06/603

そりゃ、Htmlを長くするとメモリー足らなくなりますね。

ここに分かりやす解説がありました。
https://learn.adafruit.com/memories-of-an-arduino/you-know-you-have-a-memory-problem-when-dot-dot-dot

とりあえずF()マクロで100バイトくらい節約!

次はPROGMEMの登場。

コンテンツはフラッシュにおけるようになりバッファに余裕ができました。

これでコンテンツに安心してjavascriptを追加できます。

Arduino で遊ぼう(6) ネットワークカメラ

Pro Micro 3.3V + XBee WiFi + C1098-SS
でネットワークカメラになりました。

でも、RAMが辛いのかHTMLを少し長くしたりするとうまく動かなくなる。

カメラのライブラリのチューニングが必要かな。

とりあえず、今のスケッチ

〜〜〜〜〜〜

#include <SPI.h>
#include <CameraC1098.h>

/*
 XBee WiFi Connected Serial.
 XBee works in API Mode.

 Receive Serial and Parse API packet,
 then echo back by API packet.
 */
/**
 * 送信パケットの生成
 */
int makeXBeeApiSendIp(byte* pPacket, unsigned short u16Size, byte* pbIpAddrDst,
byte* pbPortDst, byte* pbPayload, word length) {
if (u16Size < length + 16) {
Serial.println("buffer too short");
return -1;
}

// パケット生成
pPacket[0] = 0x7E;
// length
u16Size = length + 12;
pPacket[1] = u16Size >> 8;
pPacket[2] = u16Size & 0x00FF;
// API Cmd
pPacket[3] = 0x20;
// FrameID
pPacket[4] = 0x00;
// IpAddrDst
pPacket[5] = pbIpAddrDst[0];
pPacket[6] = pbIpAddrDst[1];
pPacket[7] = pbIpAddrDst[2];
pPacket[8] = pbIpAddrDst[3];
// PortDst
pPacket[9] = pbPortDst[0];
pPacket[10] = pbPortDst[1];
// PortSrc
pPacket[11] = 0x26;
pPacket[12] = 0x16;
// Protocol
pPacket[13] = 0x01; //< TCP
// Transmit Options
// pPacket[14] = 0x00; //< Leave Socket open
pPacket[14] = 0x02; //< Terminate Socket after tx complete

// Payload
for (int i = 0; i < length; i++) {
pPacket[15 + i] = pbPayload[i];
}
// チェックサム計算
byte sum = 0;
for (int i = 0; i < length + 12; i++) {
sum += pPacket[3 + i];
}
pPacket[length + 15] = 0xFF - sum;

return length + 16;
}

/**
 * 受信パケットのダンプ
 */
void printPayload(byte* pPayload, word length) {
if (0 < length) {
// Serial.println("dump");
for (word i = 0; i < length; i++) {
// Serial.print(pPayload[i], HEX);
// Serial.print(",");
Serial.print((char) pPayload[i]);
}
// Serial.println();
}
}

/**
 * 受信パケットのパース
 */
byte g_pbIpAddrSrc[4];
byte g_pbPortSrc[2];
byte* g_pbPayload;
int parseXBeeApiReceiveIp(byte* pPacket, unsigned short u16Size,
byte* pbIpAddrSrc, byte* pbPortSrc, byte** ppbPayload) {
// APIコード確認
if (0xB0 != pPacket[3]) {
// Serial.print("wrong api code:");
// Serial.println(pPacket[3]);
return -1;
}
// 送信元IPアドレス取得
pbIpAddrSrc[0] = pPacket[4];
pbIpAddrSrc[1] = pPacket[5];
pbIpAddrSrc[2] = pPacket[6];
pbIpAddrSrc[3] = pPacket[7];
//        Serial.write(pbIpAddrSrc, 4);
//        Serial.println();
// 送信元ポート取得
pbPortSrc[0] = pPacket[10];
pbPortSrc[1] = pPacket[11];
//        Serial.write(pbPortSrc, 2);
//        Serial.println();
// ペイロード取得
*ppbPayload = &pPacket[14];

//        Serial.println(pPacket[1]);
//        Serial.println(pPacket[2]);

return ((int) pPacket[1] << 8) + (int) pPacket[2] - 11;
}

/**
 * 受信処理
 */
#define RECEIVE_IP 1
unsigned char u8ReceiveMode = 0;
#define RECEIVE_MODE_IDLE 0
#define RECEIVE_MODE_LEN1 1
#define RECEIVE_MODE_LEN2 2
#define RECEIVE_MODE_DATA 3
#define RECEIVE_MODE_CS 4
#define APIPACKET_SIZE_MAX 512
byte g_pu8ApiPacket[APIPACKET_SIZE_MAX];
unsigned short g_u16ApiPacketSize;
unsigned short g_u16ApiPacketLength;
int parseXBeeApiChar(byte data) {
// Serial.println(data, HEX);

switch (u8ReceiveMode) {
case RECEIVE_MODE_IDLE:
// wait for "0x7E"
if (0x7E == data) {
g_u16ApiPacketSize = 0;
g_u16ApiPacketLength = 0;
g_pu8ApiPacket[g_u16ApiPacketSize++] = data;
u8ReceiveMode = RECEIVE_MODE_LEN1;
// Serial.println("api start");
}
break;
case RECEIVE_MODE_LEN1:
g_pu8ApiPacket[g_u16ApiPacketSize++] = data;
u8ReceiveMode = RECEIVE_MODE_LEN2;
break;
case RECEIVE_MODE_LEN2:
g_pu8ApiPacket[g_u16ApiPacketSize++] = data;
u8ReceiveMode = RECEIVE_MODE_DATA;
g_u16ApiPacketLength = ((unsigned short) g_pu8ApiPacket[1] << 8)
+ (unsigned short) g_pu8ApiPacket[2];
// Serial.print("get len :");
// Serial.println(g_u16ApiPacketLength);
if (g_u16ApiPacketLength > (APIPACKET_SIZE_MAX - 4)) {
Serial.println("invalid data len");
u8ReceiveMode = RECEIVE_MODE_IDLE;
}
break;
case RECEIVE_MODE_DATA:
g_pu8ApiPacket[g_u16ApiPacketSize++] = data;
if ((g_u16ApiPacketSize - 3) >= g_u16ApiPacketLength) {
u8ReceiveMode = RECEIVE_MODE_CS;
// Serial.println("get data");
}
break;
case RECEIVE_MODE_CS:
g_pu8ApiPacket[g_u16ApiPacketSize++] = data;
u8ReceiveMode = RECEIVE_MODE_IDLE;
// Serial.println("get cs");
return RECEIVE_IP;
break;
default:
break;
}
return 0;
}

/**
 * SPI制御
 */
byte XBEE_SPI_ATTEN = 4;
byte XBEE_SPI_CS = 5;
/**
 * SPI初期化
 */
void spiInit() {
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);
SPI.setClockDivider(SPI_CLOCK_DIV4); //< 8MHz/4=2MHz
SPI.begin();

// XBee SPI ATTEN
pinMode(XBEE_SPI_ATTEN, INPUT);

// XBee SPI CS
pinMode(XBEE_SPI_CS, OUTPUT);
digitalWrite(XBEE_SPI_CS, HIGH);

}

/**
 * SPI受信
 * @note 受信のみ
 */
int spiReceive() {
int len = 0;
if (LOW == digitalRead(XBEE_SPI_ATTEN)) {
digitalWrite(XBEE_SPI_CS, LOW);
if (RECEIVE_IP == parseXBeeApiChar(SPI.transfer(0x00))) {
len = parseXBeeApiReceiveIp(g_pu8ApiPacket, g_u16ApiPacketSize,
g_pbIpAddrSrc, g_pbPortSrc, &g_pbPayload);
Serial.print("[receive ip packet:");
Serial.print(len);
Serial.print("]");
Serial.println();
printPayload(g_pbPayload, len);
}

if (HIGH == digitalRead(XBEE_SPI_ATTEN)) {
digitalWrite(XBEE_SPI_CS, HIGH);
}
}

return len;
}

/**
 * SPI送信
 * TODO 送信中の受信処理
 */
void spiSend(byte* pData, word length) {
digitalWrite(XBEE_SPI_CS, LOW);
for (int i = 0; i < length; i++) {
SPI.transfer(pData[i]);
}
digitalWrite(XBEE_SPI_CS, HIGH);
}

static const char gsc_pcHtmlHeader[] = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"Connection: close\r\n"
"Content-Length: ";
#define USE_JAVASCRIPT
#ifdef USE_JAVASCRIPT
static const char gsc_pcHtmlContents1[] =
"<html>"
"<head>"
"<script type=\"text/javascript\">\r\n"
"myImage = new Image();\r\n"
"count = 0;\r\n"
"function loadImage(url) {\r\n"
"myImage.onload = function(){\r\n"
"loadImage(url);\r\n"
"document.getElementById(\"img_mine\").src = myImage.src;\r\n"
;
static const char gsc_pcHtmlContents2[] =
"}\r\n"
"myImage.src = url + \"?\" + count.toString();\r\n"
"count++;\r\n"
"}\r\n"
"</script>"
"</head>\r\n"
"<body>"
//"<h1>hello world</h1>"
//"message from Arduino<br/>"
"pro micro 3.3V<br/>"
//"with XBee WiFi<br/>"
;
static const char gsc_pcHtmlContents3[] =
//"connected by SPI<br>"
//"<address>su4yamamoto</address>"
"<br/>"
"<img id=\"img_mine\"/>\r\n"
"<script type=\"text/javascript\">\r\n"
"loadImage(\"img.jpg\");\r\n"
"</script>\r\n"
"</body>"
"</html>"
;
#else // #ifdef USE_JAVASCRIPT
static const char gsc_pcHtmlContents1[] =
"<html>"
"<head>"
"<meta http-equiv=\"Refresh\" content=\"5\">"
"</head>"
"<body>"
"<h1>hello world</h1>"
"message from Arduino<br/>"
"pro micro 3.3V<br/>"
"with XBee WiFi<br/>"
"connected by SPI<br>"
"<address>su4yamamoto</address>"
"<br/>"
"<img src='img.jpg'/>"
"</body>"
"</html>";
#endif // #ifdef USE_JAVASCRIPT
static const char gsc_pcHtmlHeaderJpeg[] = "HTTP/1.1 200 OK\r\n"
"Content-Type: image/jpeg\r\n"
"Connection: close\r\n"
"Content-Length: ";
static const char gsc_pcHtmlLineFeed[] = "\r\n\r\n";
static const char gsc_pcHtmlNotFound[] = "HTTP/1.1 404 Not Found\r\n"
"Content-Type: text/plain\r\n"
"Content-Length: 9\r\n"
"\r\n"
"Not Found\r\n";

CameraC1098 camera(&Serial1);
uint32_t pictureSizeCount = 0;
/**
 * This callback is called EVERY time a JPEG data packet is received.
 */
void getJPEGPicture_callback(uint32_t pictureSize, uint32_t packageSize,
uint16_t packageCount, byte* package) {
if (0 == pictureSizeCount) {
Serial.println();
Serial.print("jpeg size:");
Serial.println(pictureSize);
#ifndef HTML_HELLOWORLD
// first time -> send size info
char pcLength[16];
String strLength = String(pictureSize, DEC);
strLength.toCharArray(pcLength, sizeof(pcLength));
spiSend(g_pu8ApiPacket,
makeXBeeApiSendIp(g_pu8ApiPacket, APIPACKET_SIZE_MAX,
g_pbIpAddrSrc, g_pbPortSrc, (byte*) pcLength,
strLength.length()));
spiSend(g_pu8ApiPacket,
makeXBeeApiSendIp(g_pu8ApiPacket, APIPACKET_SIZE_MAX,
g_pbIpAddrSrc, g_pbPortSrc, (byte*) gsc_pcHtmlLineFeed,
sizeof(gsc_pcHtmlLineFeed) - 1));
#endif
}
// packageSize is the size of the picture part of the package
pictureSizeCount += packageSize;

// Serial.write(package, packageSize);
Serial.print(packageSize);
Serial.print(":");
Serial.println(pictureSizeCount);
#ifndef HTML_HELLOWORLD
spiSend(g_pu8ApiPacket,
makeXBeeApiSendIp(g_pu8ApiPacket, APIPACKET_SIZE_MAX, g_pbIpAddrSrc,
g_pbPortSrc, package, packageSize));
#endif//#ifdef HTML_HELLOWORLD
if (pictureSizeCount >= pictureSize) {
spiSend(g_pu8ApiPacket,
makeXBeeApiSendIp(g_pu8ApiPacket, APIPACKET_SIZE_MAX,
g_pbIpAddrSrc, g_pbPortSrc, (byte*) gsc_pcHtmlLineFeed,
sizeof(gsc_pcHtmlLineFeed) - 1));
Serial.flush();
Serial.println();
Serial.println("finished");
}
}
void getJpegImage() {

if (!camera.sync(CameraC1098::BAUD57600)) {
Serial.println("Sync failed");
return;
}

if (!camera.initial(CameraC1098::BAUD57600, CameraC1098::JR_320x240)) {
Serial.println("Initial failed");
return;
}
if (!camera.setPackageSize(64)) {
Serial.println("Package size failed.");
return;
}

if (!camera.snapshot()) {
Serial.println("Snapshot failed.");
return;
}

pictureSizeCount = 0;
if (!camera.getJPEGPicture(PROCESS_DELAY, &getJPEGPicture_callback)) {
Serial.println("Get JPEG failed.");
return;
}
}

byte toggle = 0;
void setup() {
// SPIの初期設定
spiInit();

Serial.begin(115200); //This pipes to the serial monitor
Serial1.begin(14400);
}
void loop() {
int len = spiReceive();

if (0 < len) {
// html reply
// Check Request
String strReq = String((char*) g_pbPayload);
                if (strReq.startsWith("GET /index.html")) {
spiSend(g_pu8ApiPacket,
makeXBeeApiSendIp(g_pu8ApiPacket, APIPACKET_SIZE_MAX,
g_pbIpAddrSrc, g_pbPortSrc,
(byte*) gsc_pcHtmlHeader,
sizeof(gsc_pcHtmlHeader) - 1));
char pcLength[16];
#ifdef USE_JAVASCRIPT
String strLength = String(
                                          sizeof(gsc_pcHtmlContents1) - 1
                                            + sizeof(gsc_pcHtmlContents2) - 1
                                            + sizeof(gsc_pcHtmlContents3) - 1
                                            , DEC);
#else //#ifdef USE_JAVASCRIPT
String strLength = String(sizeof(gsc_pcHtmlContents1) - 1, DEC);
#endif //#ifdef USE_JAVASCRIPT
strLength.toCharArray(pcLength, sizeof(pcLength));
spiSend(g_pu8ApiPacket,
makeXBeeApiSendIp(g_pu8ApiPacket, APIPACKET_SIZE_MAX,
g_pbIpAddrSrc, g_pbPortSrc, (byte*) pcLength,
strLength.length()));
spiSend(g_pu8ApiPacket,
makeXBeeApiSendIp(g_pu8ApiPacket, APIPACKET_SIZE_MAX,
g_pbIpAddrSrc, g_pbPortSrc, (byte*) gsc_pcHtmlLineFeed,
sizeof(gsc_pcHtmlLineFeed) - 1));
spiSend(g_pu8ApiPacket,
makeXBeeApiSendIp(g_pu8ApiPacket, APIPACKET_SIZE_MAX,
g_pbIpAddrSrc, g_pbPortSrc, (byte*) gsc_pcHtmlContents1,
sizeof(gsc_pcHtmlContents1) - 1));
#ifdef USE_JAVASCRIPT
spiSend(g_pu8ApiPacket,
makeXBeeApiSendIp(g_pu8ApiPacket, APIPACKET_SIZE_MAX,
g_pbIpAddrSrc, g_pbPortSrc, (byte*) gsc_pcHtmlContents2,
sizeof(gsc_pcHtmlContents2) - 1));
spiSend(g_pu8ApiPacket,
makeXBeeApiSendIp(g_pu8ApiPacket, APIPACKET_SIZE_MAX,
g_pbIpAddrSrc, g_pbPortSrc, (byte*) gsc_pcHtmlContents3,
sizeof(gsc_pcHtmlContents3) - 1));
#endif//#ifdef USE_JAVASCRIPT
spiSend(g_pu8ApiPacket,
makeXBeeApiSendIp(g_pu8ApiPacket, APIPACKET_SIZE_MAX,
g_pbIpAddrSrc, g_pbPortSrc, (byte*) gsc_pcHtmlLineFeed,
sizeof(gsc_pcHtmlLineFeed) - 1));
                }
else if (strReq.startsWith("GET /img.jpg")) {
spiSend(g_pu8ApiPacket,
makeXBeeApiSendIp(g_pu8ApiPacket, APIPACKET_SIZE_MAX,
g_pbIpAddrSrc, g_pbPortSrc,
(byte*) gsc_pcHtmlHeaderJpeg,
sizeof(gsc_pcHtmlHeaderJpeg) - 1));
getJpegImage();
} else {
Serial.println("invalid http request");
spiSend(g_pu8ApiPacket,
makeXBeeApiSendIp(g_pu8ApiPacket, APIPACKET_SIZE_MAX,
g_pbIpAddrSrc, g_pbPortSrc,
(byte*) gsc_pcHtmlNotFound,
sizeof(gsc_pcHtmlNotFound) - 1));
return;
}

}

#ifndef HTML_HELLOWORLD
if (0 < Serial.available()) {
while (-1 != Serial.read())
;
getJpegImage();
}
#endif
}

2014年10月29日水曜日

Arduino で遊ぼう(5) シリアルJPEGカメラをつなぐ

ふ 以前に買っていたシリアルjpegカメラをつなげます。

http://arms22.blog91.fc2.com/blog-entry-261.html
にArduinoのサンプルがあったので利用させていただきました。

C1098むけに若干の修正とハードシリアルに変更させていただきました。

※最初、pro microの容量が足らないのかうまくうごきませんでした。
電源別にしてうまく動きました。
http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Dev/Arduino/Boards/Pro_Micro_v13.pdf
によると500mAは供給出来るはずなので大丈夫そうなんですが。。。

2014/10/30 追記
よくしらべるとプレップボードでの接触不良でした。

2014年10月24日金曜日

Arduino て遊ぼう(4) SPIでXBeeとつなぐ

すシリアルでつなげたものを、SPIに移植します。

結線は
xbee             ----     Pro Micro
(slave)                       (master)
18 SPI CLK  <--- 15 SPI CLK
17 SPI SLAVE 
    #SELECT <--- 5 digital out
19 SPI SLAVE 
    #ATTEN    ---> 4 digital in
     * use interrupt 
11 SPI MOSI <--- 16 SPI MOSI
4 SPI MISO   ---> 14 SPI MISO

xbeeはDout(2)をlowに落として、強制的にSPIモードにしておきます。

Arduino は
まずは、受信処理のみ。
ATTENがlowになったらCSを落として一通り受信します。
受信完了でパケット処理します。
(SPIは高速なので先に受信してしまうことにします)

そしてエコーバック。本当は、送信中もATTENを見てやらないといけませんが、、それはまた次回。

エコーバックはうまくいったので、
定型のHTMLを返すようして
簡易webサーバーの出来上がり(^^)

Arduino で遊ぼう(3) XBeeとシリアル接続してAPIモード

Arduino とXBee wifiをシリアルで接続して、APIモードで動かしました。

XBee wifiにはtelnetで接続すると、
受信パケットをエコーバックします。

シリアルのボーレートは57600bpsまでしかうごきませんでした。

とりあえずのコード
(汚い…、。)

/*
 XBee WiFi Connected Serial.
 XBee works in API Mode.

 Receie Serial and Parse API packet,
 then echo back by API packet.
 */

/**
 * 送信パケットの生成
 */
int makeXBeeApiSendIp(byte* pPacket, unsigned short u16Size,
byte* pbIpAddrDst, byte* pbPortDst, byte* pbPayload, word length)
{
if(u16Size < length + 16)
{
Serial.println("buffer too short");
return -1;
}

// パケット生成
pPacket[0] = 0x7E;
// length
        u16Size = length + 12;
pPacket[1] = u16Size >> 8;
pPacket[2] = u16Size & 0x00FF;
// API Cmd
pPacket[3] = 0x20;
// FrameID
pPacket[4] = 0x00;
// IpAddrDst
pPacket[5] = pbIpAddrDst[0];
pPacket[6] = pbIpAddrDst[1];
pPacket[7] = pbIpAddrDst[2];
pPacket[8] = pbIpAddrDst[3];
// PortDst
pPacket[9] = pbPortDst[0];
pPacket[10] = pbPortDst[1];
// PortSrc
pPacket[11] = 0x26;
pPacket[12] = 0x16;
// Packet Type
pPacket[13] = 0x01; //< TCP, Connection Keep
//
pPacket[14] = 0x00;
// Payload
for(int i=0; i<length; i++)
{
pPacket[15 + i] = pbPayload[i];
}
// チェックサム計算
byte sum = 0;
for(int i=0; i<length + 12; i++)
{
sum += pPacket[3 + i];
}
pPacket[length + 15] = 0xFF - sum;

return length + 16;
}

/**
 * 受信パケットのダンプ
 */
void printPayload(byte* pPayload, word length)
{
  if(0 < length)
  {
    Serial.println("dump");
for(word i = 0; i<length; i++)
{
Serial.print(pPayload[i], HEX);
Serial.print(",");
}
        Serial.println();
  }
}

/**
 * 受信パケットのパース
 */
byte g_pbIpAddrSrc[4];
byte g_pbPortSrc[2];
byte* g_pbPayload;
int parseXBeeApiReceiveIp(byte* pPacket, unsigned short u16Size,
byte* pbIpAddrSrc, byte* pbPortSrc, byte** ppbPayload) {
// APIコード確認
if (0xB0 != pPacket[3]) {
// Serial.print("wrong api code:");
// Serial.println(pPacket[3]);
return -1;
}
// 送信元IPアドレス取得
pbIpAddrSrc[0] = pPacket[4];
pbIpAddrSrc[1] = pPacket[5];
pbIpAddrSrc[2] = pPacket[6];
pbIpAddrSrc[3] = pPacket[7];
//        Serial.write(pbIpAddrSrc, 4);
//        Serial.println();
// 送信元ポート取得
pbPortSrc[0] = pPacket[10];
pbPortSrc[1] = pPacket[11];
//        Serial.write(pbPortSrc, 2);
//        Serial.println();
// ペイロード取得
*ppbPayload = &pPacket[14];

//        Serial.println(pPacket[1]);
//        Serial.println(pPacket[2]);

return ((int) pPacket[1] << 8) + (int) pPacket[2] - 11;
}

/**
 * 受信処理
 */
#define RECEIVE_IP 1
unsigned char u8ReceiveMode = 0;
#define RECEIVE_MODE_IDLE 0
#define RECEIVE_MODE_LEN1 1
#define RECEIVE_MODE_LEN2 2
#define RECEIVE_MODE_DATA 3
#define RECEIVE_MODE_CS 4
#define APIPACKET_SIZE_MAX 1024
byte g_pu8ApiPacket[APIPACKET_SIZE_MAX];
unsigned short g_u16ApiPacketSize;
unsigned short g_u16ApiPacketLength;
int parseChar(byte data) {
// Serial.println(data, HEX);

switch (u8ReceiveMode) {
case RECEIVE_MODE_IDLE:
// wait for "0x7E"
if (0x7E == data) {
g_u16ApiPacketSize = 0;
g_u16ApiPacketLength = 0;
g_pu8ApiPacket[g_u16ApiPacketSize++] = data;
u8ReceiveMode = RECEIVE_MODE_LEN1;
// Serial.println("api start");
}
break;
case RECEIVE_MODE_LEN1:
g_pu8ApiPacket[g_u16ApiPacketSize++] = data;
u8ReceiveMode = RECEIVE_MODE_LEN2;
break;
case RECEIVE_MODE_LEN2:
g_pu8ApiPacket[g_u16ApiPacketSize++] = data;
u8ReceiveMode = RECEIVE_MODE_DATA;
g_u16ApiPacketLength = ((unsigned short) g_pu8ApiPacket[1] << 8)
+ (unsigned short) g_pu8ApiPacket[2];
// Serial.print("get len :");
// Serial.println(g_u16ApiPacketLength);
if (g_u16ApiPacketLength > (APIPACKET_SIZE_MAX - 4)) {
Serial.println("invalid data len");
u8ReceiveMode = RECEIVE_MODE_IDLE;
}
break;
case RECEIVE_MODE_DATA:
g_pu8ApiPacket[g_u16ApiPacketSize++] = data;
if ((g_u16ApiPacketSize - 3) >= g_u16ApiPacketLength) {
u8ReceiveMode = RECEIVE_MODE_CS;
// Serial.println("get data");
}
break;
case RECEIVE_MODE_CS:
g_pu8ApiPacket[g_u16ApiPacketSize++] = data;
u8ReceiveMode = RECEIVE_MODE_IDLE;
// Serial.println("get cs");
return RECEIVE_IP;
break;
default:
break;
}
return 0;
}

byte RXLED = 13;
byte toggle = 0;

void setup() {
pinMode(RXLED, OUTPUT);  // Set RX LED as an output
// TX LED is set as an output behind the scenes

Serial.begin(115200); //This pipes to the serial monitor
Serial1.begin(4800); //This is the UART, pipes to sensors attached to board
}

void loop() {
if (0 < Serial.available()) {
                byte data = Serial.read();
Serial1.write(g_pu8ApiPacket, makeXBeeApiSendIp(g_pu8ApiPacket, APIPACKET_SIZE_MAX, g_pbIpAddrSrc, g_pbPortSrc, &data, 1));
if (0 == toggle) {
digitalWrite(RXLED, LOW);   // set the LED on
TXLED0; //TX LED is not tied to a normally controlled pin
toggle = 1;
} else {
digitalWrite(RXLED, HIGH);    // set the LED off
TXLED1;
toggle = 0;
}
}
if (0 < Serial1.available()) {
// Serial.write(parseChar(Serial1.read()));
if (RECEIVE_IP == parseChar(Serial1.read())) {
int len = parseXBeeApiReceiveIp(g_pu8ApiPacket, g_u16ApiPacketSize,
g_pbIpAddrSrc, g_pbPortSrc, &g_pbPayload);
Serial.print("receive ip packet:");
Serial.println(len);

printPayload(g_pbPayload, len);

// echo
                        byte data = *g_pbPayload;
Serial1.write(g_pu8ApiPacket, makeXBeeApiSendIp(g_pu8ApiPacket, APIPACKET_SIZE_MAX, g_pbIpAddrSrc, g_pbPortSrc, &data, 1));
}
}
}

2014年10月21日火曜日

Arduino で遊ぼう(2) xbee とspiで接続[情報編]

xbee ---- Pro Micro
(slave)     (master)
18 SPI CLK  <--- 15 SPI CLK
17 SPI SLAVE 
    #SELECT <--- 5 digital out
19 SPI SLAVE 
    #ATTEN    ---> 4 digital in
     * use interrupt 
11 SPI MOSI <--- 16 SPI MOSI
4 SPI MISO   ---> 14 SPI MISO

xbee wifiのspiは
spi mode 0, MSB first

pin2(dout)をlowで起動すると強制的にspiモードになる。

arduinoは
SPI.setBitOrder(MSBFIRST)
SPI.setDataMode(SPI_MODE0)
SPI.setClockDivider(SPI_CLOCK_DIV4)
   -> 8MHzの4分周で2MHz

XBeeのAPIモードでの送信コマンドは

最後のチエックサムが。。。

digiにドキュメントがありました。
<http://www.digi.com/support/kbase/kbaseresultdetl?id=2206>
普通にlength bytes の後ろからの和をFFから引けばいいですね。

2014.10.23 追記
まずは、シリアルでxbeeをapiモードで動かした。
xbee 192.168.111.200:9750
pc 192.168.111.210で接続
xbeeからtcp送信時のシリアルデータ例
(pcのポートはcb 9b)
7E 00 0d 20 01 c0 a8 6f d2 cb 9b 26 16 01 00 31 61
"1"を送信
 



Arudinoで遊ぼう(1) 構想

今更だけど、arduinoを触ってみようと思う。

xbeeと前に買ったシリアル出力JPEGカメラをつなげてカメラ付きたまロボwebサーバー版を作りたい。
(以前はxbeeのapiモードをudpで使ったりシリアル透過でカメラ制御していたので専用のiosアプリだった。ディベロッパーライセンスは切れたので、もうiosアプリ作れない。。。し)

arduino はpro micro 3.3Vでxbeeにもカメラにも直結。電源は前のたまロボ同様にDCDCで昇圧。モータードライバはスイッチサイエンスの
POLOLU-2135 デュアルモータードライバDRV8835
で、前のより小さい。

シリアルは、arduino のハードシリアルとソフトシリアルでいいかと思ってもいたが、ソフトシリアルは9600bpsがいいとこらしい。

これは厳しいです。

で、xbeeはspiで行けないかと考えています。
こんな文書がありました。
<a href=http://www.digi.com/support/kbase/kbaseresultdetl?id=3362>An Introduction to SPI on XBee</a>
いけるかな?

xbeeは3.5MHzまで対応しているみたいなのでpro microは1/4分周で、
うまく行けば、2MHz⁈