電圧計を作る ③ ADS8699のスケッチ その2 アナログ電圧の読み出し
前回、12.288 ~–12.288Vが入力範囲のデフォルトから、6.144~–6.144Vの入力レンジであるRANGE_SEL_REG Register (address = 14h)を0010bに変更しました。この状態で、入力電圧を読みます。
●下位バイトを読めない
18ビットのデータは、DATAOUT_CTL_REG RegisterのD[31:14] に入っています。D[31:16]は、上位16ビットを読むとえられますが、残りの2ビットは下位16ビットを読まないとえられません。しかし、読めません。
TI社のQ&A(ADS8691: how to read register value of bit[0:15])に、次のように書かれています。
Here is an example to use READ_HWORD command to read the 16-bit of ALARM_H_TH_REG Register:
(Byte 0 Address for bits 7-0 = 24h, Byte 1 Address for bits 15-8 = 25h, Byte 2 Address for bits 23-16 = 26h, Byte 3 Address for bits 31-24 = 27h)
- Use Read_HWORD command to read the 16-bit (0~15 bit) of register:
Data frame: <11001_xx> <0_0010_0100><00000000><00000000>
- Use Read_HWORD command to read the 16-bit (16~31 bit) of register:
Data frame: <11001_xx> <0_0010_0110><00000000><00000000>
Please note:
A “0” should be added prior to the address to have a 9-bit address: 0_0010_0100b for address 24h. LSB of the 9-bit address is always ignored and considered as 0b. To write/read both byte 0 and byte 1(or byte 2 and byte 3) in one command, the low byte address (byte 0 or 2) should be used. If the address of byte 1 or 3 is given, the LSB (bit 0) will be ignored, because it is a 16 bit address now. HWORD commands can be only written to the addresses of byte 0+byte 1 or byte 2+byte 3 and so on. They cannot be used for byte 1+ byte 2.
しかし、読めませんでした。
●スケッチ
16ビットを読む形で、スケッチを書きました。試行を何度も行ったので、少し冗長な記述になっています。
#include <SPI.h>
#define CS 9
#define RST 8
const float LSB = 46.875; // 1.5V x Vref 0010b
//ADS8699
SPISettings settings(10000000, MSBFIRST, SPI_MODE0);
void setup() {
pinMode(RST, OUTPUT);
digitalWrite(RST, HIGH); // reset
delay(0.1);
digitalWrite(RST, LOW);
delay(0.1);
digitalWrite(RST, HIGH);
pinMode(CS, OUTPUT);
digitalWrite(CS, HIGH);
Serial.begin(9600);
while(!Serial);
Serial.println("\nADS8699 test");
SPI.begin();
Serial.println("\write DATAOUT_CTL_REG Register---- ");
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
uint8_t highByte = SPI.transfer(0b1101000); // 11010_00_ LS DATAOUT_CTL_REG Register
uint8_t midByte = SPI.transfer(0b00010000); // 0x10 _0
uint8_t lowByte = SPI.transfer(0x00); //
uint8_t lowlowByte= SPI.transfer(0b00000000); // real data
digitalWrite(CS, HIGH);
delay(0.2);
Serial.println("\write range ------ ");
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
highByte = SPI.transfer(0b11010100); // 11010_10_ LS
midByte = SPI.transfer(0b00101000); // 0x14 _0
lowByte = SPI.transfer(0x00); //
lowlowByte = SPI.transfer(0b00000010); //
digitalWrite(CS, HIGH);
SPI.endTransaction();
delay(0.2);
}
int read_range(){
Serial.print("\nread range ------ ");
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
uint8_t highByte = SPI.transfer(0b11001000); // 11001_xx_ read range1
uint8_t midByte = SPI.transfer(0b00101000); // 14
uint8_t lowByte = SPI.transfer(0x00); //
uint8_t lowlowByte = SPI.transfer(0x00); //
digitalWrite(CS, HIGH);
SPI.endTransaction();
delay(0.2);
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
highByte = SPI.transfer(0b11001000); // 11001_xx_ read range2
midByte = SPI.transfer(0b00101000); // 14
lowByte = SPI.transfer(0x00); //
lowlowByte = SPI.transfer(0x00); //
digitalWrite(CS, HIGH);
SPI.endTransaction();
Serial.print(highByte,BIN);Serial.println(midByte,BIN);
Serial.print(highByte,HEX);Serial.print("," );
Serial.print(midByte,HEX); //Serial.print("," );
Serial.println("-" );
// Serial.print("\nread range 1byte------ ");
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
highByte = SPI.transfer(0b01001000); // 11001_xx_ read range1
midByte = SPI.transfer(0b00101000); // 14
lowByte = SPI.transfer(0x00); //
lowlowByte = SPI.transfer(0x00); //
digitalWrite(CS, HIGH);
SPI.endTransaction();
delay(0.2);
Serial.print("\nread range 1byte------ ");
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
highByte = SPI.transfer(0b01001000); // 11001_xx_ read range1
midByte = SPI.transfer(0b00101000); // 14
lowByte = SPI.transfer(0x00); //
lowlowByte = SPI.transfer(0x00); //
digitalWrite(CS, HIGH);
SPI.endTransaction();
Serial.println(highByte,BIN);
Serial.print(highByte,HEX);Serial.print("," );
Serial.println(midByte,HEX); //Serial.print("," );
delay(0.2);
}
double read_voltdata( ) {
Serial.println("\nread voltage ------");
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
uint8_t highByte = SPI.transfer(0b1100100); // 11001_xx_read
uint8_t midByte = SPI.transfer(0b00010000); // 10 00010000 DATAOUT_CTL_REG Register
uint8_t lowByte = SPI.transfer(0x00); //
uint8_t lowlowByte = SPI.transfer(0x00); //
digitalWrite(CS, HIGH);
SPI.endTransaction();
delay(0.2);
//Serial.println("\n-1 - - -");
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
uint32_t highByte0 = SPI.transfer(0b1100100); // read
uint32_t midByte0 = SPI.transfer(0b00010010); // 12
lowByte = SPI.transfer(0x00); //
lowlowByte = SPI.transfer(0x00); //
digitalWrite(CS, HIGH);
SPI.endTransaction();
//Serial.println("\n-2 - - -");
//Serial.print(highByte0,BIN);Serial.println(midByte0,BIN);
//Serial.print(highByte0,HEX);Serial.print("," );
//Serial.print(midByte0,HEX);Serial.print(" ; " );
//Serial.println("\n------");
delay(0.1);
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
highByte = SPI.transfer(0b11001000); // read
midByte = SPI.transfer(0b00010010); // 12
lowByte = SPI.transfer(0x00); //
lowlowByte = SPI.transfer(0x00); //
digitalWrite(CS, HIGH);
SPI.endTransaction();
//Serial.println("\n-3 - - -");
//Serial.println(highByte,BIN);
Serial.print(highByte,HEX);Serial.print("," );
Serial.print(midByte,HEX);Serial.print(" ; " );
uint32_t data = ((uint32_t)highByte << 8 | (uint32_t)midByte) << 2 ;
//Serial.print(data,HEX);Serial.print(" , " );Serial.print(data*LSB /1000000 ,8);Serial.println("V" );
data = data - 0x20000;
if (data >=0) {
Serial.print(data,HEX);Serial.print(" , " );Serial.print(data*LSB*2 /1000000 ,4);Serial.println("V" );
}else if(data < 0){
Serial.print(data,HEX);Serial.print(" , " );Serial.print(-(-1*data*LSB*2 /1000000 ),4);Serial.println("V" );
}
}
void loop() {
//read_range();
read_voltdata();
delay(3000);
}
実行例です。入力はArduinoの3.3V端子につないであります。
●SPIの転送
ずっとSPIのライブラリは8ビット単位だと思っていました。最近のArduiono.ccをみると、SPI.transfer16()と複数同時に転送ができるSPI.transfer(バッファ,転送数)が追加されていました。
SPI.transfer16()の使用例です。スケッチ自体がうまく動いていません。
#include <SPI.h>
#define CS 9
#define RST 8
const float LSB = 46.875; // 1.5V x Vref 0010b
//ADS8699
SPISettings settings(1000000, MSBFIRST, SPI_MODE0);
void setup() {
pinMode(RST, OUTPUT);
digitalWrite(RST, HIGH); // reset
delay(0.1);
digitalWrite(RST, LOW);
delay(0.1);
digitalWrite(RST, HIGH);
pinMode(CS, OUTPUT);
digitalWrite(CS, HIGH);
Serial.begin(9600);
while(!Serial);
Serial.println("\nADS8699 test");
SPI.begin();
Serial.println("\write DATAOUT_CTL_REG Register---- ");
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
// 11010_00_ LS DATAOUT_CTL_REG Register 0x10
uint16_t highWord = SPI.transfer16(0b1101000000010000);
uint16_t lowWord = SPI.transfer16(0x0000);
digitalWrite(CS, HIGH);
SPI.endTransaction();
delay(0.2);
Serial.println("\write range ------ ");
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
// 11010_10_ LS 0x14
highWord = SPI.transfer16(0b11010100000101000);
lowWord = SPI.transfer16(0x0000); //
digitalWrite(CS, HIGH);
SPI.endTransaction();
delay(0.2);
}
double read_voltdata( ) {
Serial.println("\nread voltage ------");
// -1
Serial.println("-1 - - -");
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
uint16_t highWord = SPI.transfer16(0b1100100000010010); // 11001_xx_read
uint16_t lowWord = SPI.transfer16(0x0000);
digitalWrite(CS, HIGH);
SPI.endTransaction();
Serial.print(highWord,HEX);Serial.print("," );Serial.println(lowWord,HEX);
delay(0.2);
// -2
Serial.println("\n-2 - - -");
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
highWord = SPI.transfer16(0b1100100000010010); // 11001_xx_read
lowWord = SPI.transfer16(0x0000);
digitalWrite(CS, HIGH);
SPI.endTransaction();
Serial.print(highWord,HEX);Serial.print("," );Serial.println(lowWord,HEX);
delay(0.2);
// -3
Serial.println("\n-3 - - -");
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
highWord = SPI.transfer16(0b1100100000010010); // 11001_xx_read 12
lowWord = SPI.transfer16(0x0000);
digitalWrite(CS, HIGH);
SPI.endTransaction();
Serial.print(highWord,HEX);Serial.print("," );Serial.println(lowWord,HEX);
//uint32_t data = ((uint32_t)highByte << 24 | (uint32_t)midByte << 16 | (highByte0 << 8) & 0b11000000) >> 14;
// data = data - 0x20000;
//Serial.print(data,HEX);Serial.print(" , " );Serial.print(data*LSB /1000000 *2, 8);Serial.println("V" );
// -4
Serial.println("\n-4 - - -");
SPI.beginTransaction(settings);
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
highWord = SPI.transfer16(0b1100100000010010); // 11001_xx_read 12
lowWord = SPI.transfer16(0x0000);
digitalWrite(CS, HIGH);
SPI.endTransaction();
Serial.print(highWord,HEX);Serial.print("," );Serial.println(lowWord,HEX);
//uint32_t data1 = ((uint32_t)highByte << 24 | (uint32_t)midByte << 16 | (highByte0 << 8) & 0b11000000) >> 14;
//data1 = data1 - 0x20000;
//Serial.print(data1,HEX);Serial.print(" , " );Serial.print(data1*LSB /1000000 *2, 8);Serial.println("V" );
}
void loop() {
read_voltdata();
delay(3000);
}
波形です。下側のクロックを見ると、16ビットがひとまとまりで転送されています。
SPI.transfer(バッファ,転送数)の使用例です。スケッチ自体がうまく動いていません。
#include "SPI.h"
#define CS 9
#define RST 8
SPISettings settings(1000000, MSBFIRST, SPI_MODE0);
uint32_t* _receive_buffer;
uint32_t* receive_buffer=0;
uint8_t buffer_size = 4;
uint8_t _buffer_size=4;
uint8_t _buffer_store_num=0;
uint8_t _transmit_bytes[4];
//receive_buffer[buffer_size] = {0,0,0,0};
//_receive_buffer = receive_buffer;
//_buffer_size = buffer_size;
void setup() {
pinMode(RST, OUTPUT);
digitalWrite(RST, HIGH); // reset
delay(0.1);
digitalWrite(RST, LOW);
delay(0.1);
digitalWrite(RST, HIGH);
pinMode(CS, OUTPUT);
digitalWrite(CS, HIGH);
Serial.begin(9600);
while(!Serial);
Serial.println("\nADS8699 test");
SPI.begin();
Serial.println("\write DATAOUT_CTL_REG Register---- ");
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
uint8_t highByte = SPI.transfer(0b11010000); // 11010_00_ LS DATAOUT_CTL_REG Register
uint8_t midByte = SPI.transfer(0b00100000); // 0x10 _0
uint8_t lowByte = SPI.transfer(0x00); //
uint8_t lowlowByte= SPI.transfer(0b00000000); // real data
digitalWrite(CS, HIGH);
SPI.endTransaction();
delay(0.2);
Serial.println("\nwrite range ");
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
highByte = SPI.transfer(0b11010100); // 11010_10_ LS
midByte = SPI.transfer(0b00101000); // 0x14 _0
lowByte = SPI.transfer(0x00); //
lowlowByte = SPI.transfer(0b00000010); // 2
digitalWrite(CS, HIGH);
SPI.endTransaction();
delay(0.2);
}
void transmit(uint8_t command, uint16_t address, uint16_t data){
// Serial.print(_buffer_size,HEX);Serial.print("," ); Serial.print(_buffer_store_num,HEX);;Serial.print("," );
if(_buffer_size > _buffer_store_num){
_receive_buffer[_buffer_store_num] = 0;
_transmit_bytes[0] = (command<<1)|((address>>8)&1);
_transmit_bytes[1] = (address&0xFF);
_transmit_bytes[2] = ((data>>8)&0xFF);
_transmit_bytes[3] = (data&0xFF);
uint8_t i = 0;
digitalWrite(CS,LOW);
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
SPI.transfer(_transmit_bytes,4);
SPI.endTransaction();
digitalWrite(CS,HIGH);
//Serial.println("\n- - -" );
// Serial.print(_buffer_size,HEX);Serial.print("," ); Serial.println(_buffer_store_num,HEX);
//Serial.println("- - -" );
while(i<4){
_receive_buffer[_buffer_store_num] = (_receive_buffer[_buffer_store_num]<<8);
//Serial.print(_receive_buffer[_buffer_store_num],HEX);;Serial.println("," );
_receive_buffer[_buffer_store_num] |= _transmit_bytes[i];
//Serial.print(_receive_buffer[_buffer_store_num],HEX);;Serial.print("," );
i++;
//Serial.println("\n---" );
}
Serial.print(_receive_buffer[_buffer_store_num],HEX);;Serial.print("," );
//Serial.print(_receive_buffer[0],HEX);;Serial.print("," );Serial.println(_receive_buffer[1],HEX);
//Serial.print(_receive_buffer[2],HEX);;Serial.print("," );Serial.println(_receive_buffer[3],HEX);
// Serial.print(_receive_buffer[4],HEX);;Serial.print("," );Serial.println(_receive_buffer[5],HEX);
//Serial.print(_receive_buffer[6],HEX);;Serial.print("," );Serial.println(_receive_buffer[7],HEX);
_buffer_store_num++;
}
}
void loop() {
Serial.println("\n---");
_buffer_size=4;
_buffer_store_num=1;
Serial.println("\nLow");
//transmit(0b01100000, 0x0010, 0b0000000000000000);
transmit(0b01100100, 0x0010, 0b0000000000000000);
_buffer_size=4;
_buffer_store_num=1;
Serial.println("\nHigh0");
//transmit(0b01101010, 0x0010, 0b1111111111111101);
transmit(0b01100100, 0x0010, 0b0000000000000000);
transmit(0b01100100, 0x0010, 0b0000000000000000);
_buffer_size=4;
_buffer_store_num=1;
Serial.println("\nHigh");
transmit(0b01101010, 0x0010, 0b0000000000000000);
transmit(0b01100100, 0b00101000, 0b0000000000000000);
transmit(0b01100100, 0b00101000, 0b0000000000000000);
delay(3000);
}
実行波形です。8ビット単位ですが、8ビットの単位が密になっているようです。
●スケッチ
電圧を読んで、returnで値を戻すように修正しました。
#include <SPI.h>
#define CS 9
#define RST 8
uint8_t highByte;
uint8_t midByte;
uint8_t lowByte;
uint8_t lowlowByte;
const float LSB = 46.875; // 1.5V x Vref 0010b
//ADS8699
SPISettings settings(10000000, MSBFIRST, SPI_MODE0);
void setup() {
pinMode(RST, OUTPUT);
digitalWrite(RST, HIGH); // reset
delay(0.1);
digitalWrite(RST, LOW);
delay(0.1);
digitalWrite(RST, HIGH);
pinMode(CS, OUTPUT);
digitalWrite(CS, HIGH);
Serial.begin(9600);
while(!Serial);
Serial.println("\nADS8699 test");
SPI.begin();
Serial.println("\nwrite DATAOUT_CTL_REG Register---- ");
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
highByte = SPI.transfer(0b1101000); // 11010_00_ LS DATAOUT_CTL_REG Register
midByte = SPI.transfer(0b00010000); // 0x10 _0
lowByte = SPI.transfer(0x00); //
lowlowByte= SPI.transfer(0b00000000); // real data
digitalWrite(CS, HIGH);
SPI.endTransaction();
delay(0.2);
Serial.println("\nwrite range ------ ");
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
highByte = SPI.transfer(0b11010100); // 11010_10_ LS
midByte = SPI.transfer(0b00101000); // 0x14 _0
lowByte = SPI.transfer(0x00); //
lowlowByte = SPI.transfer(0b00000010); //
digitalWrite(CS, HIGH);
SPI.endTransaction();
delay(0.2);
}
int read_range(){
Serial.print("\nread range ------ ");
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
highByte = SPI.transfer(0b11001000); // 11001_xx_ read range1
midByte = SPI.transfer(0b00101000); // 14
lowByte = SPI.transfer(0x00); //
lowlowByte = SPI.transfer(0x00); //
digitalWrite(CS, HIGH);
SPI.endTransaction();
delay(0.2);
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
highByte = SPI.transfer(0b11001000); // 11001_xx_ read range2
midByte = SPI.transfer(0b00101000); // 14
lowByte = SPI.transfer(0x00); //
lowlowByte = SPI.transfer(0x00); //
digitalWrite(CS, HIGH);
SPI.endTransaction();
Serial.print(highByte,BIN);Serial.println(midByte,BIN);
Serial.print(highByte,HEX);Serial.print("," );
Serial.print(midByte,HEX); //Serial.print("," );
Serial.println("-" );
// Serial.print("\nread range 1byte------ ");
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
highByte = SPI.transfer(0b01001000); // 11001_xx_ read range1
midByte = SPI.transfer(0b00101000); // 14
lowByte = SPI.transfer(0x00); //
lowlowByte = SPI.transfer(0x00); //
digitalWrite(CS, HIGH);
SPI.endTransaction();
delay(0.2);
Serial.print("\nread range 1byte------ ");
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
highByte = SPI.transfer(0b01001000); // 11001_xx_ read range1
midByte = SPI.transfer(0b00101000); // 14
lowByte = SPI.transfer(0x00); //
lowlowByte = SPI.transfer(0x00); //
digitalWrite(CS, HIGH);
SPI.endTransaction();
Serial.println(highByte,BIN);
Serial.print(highByte,HEX);Serial.print("," );
Serial.println(midByte,HEX); //Serial.print("," );
delay(0.2);
}
double read_voltdata( ) {
//Serial.println("\nread voltage ------");
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
highByte = SPI.transfer(0b1100100); // 11001_xx_read
midByte = SPI.transfer(0b00010000); // 10 00010000 DATAOUT_CTL_REG Register
lowByte = SPI.transfer(0x00); //
lowlowByte = SPI.transfer(0x00); //
digitalWrite(CS, HIGH);
SPI.endTransaction();
delay(0.2);
//Serial.println("\n-1 - - -");
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
highByte = SPI.transfer(0b1100100); // read
midByte = SPI.transfer(0b00010010); // 12
lowByte = SPI.transfer(0x00); //
lowlowByte = SPI.transfer(0x00); //
digitalWrite(CS, HIGH);
SPI.endTransaction();
delay(0.1);
SPI.beginTransaction(settings);
digitalWrite(CS, LOW);
highByte = SPI.transfer(0b11001000); // read
midByte = SPI.transfer(0b00010010); // 12
lowByte = SPI.transfer(0x00); //
lowlowByte = SPI.transfer(0x00); //
digitalWrite(CS, HIGH);
SPI.endTransaction();
//Serial.println("\n-3 - - -");
//Serial.print(highByte,HEX);Serial.print("," );
//Serial.print(midByte,HEX);Serial.print(" ; " );
uint32_t data = ((uint32_t)highByte << 8 | (uint32_t)midByte) << 2 ;
if (data >=0x20000) {
data = data - 0x20000;
//Serial.print(data,HEX);Serial.print(" , " );Serial.print(data*LSB*2 /1000000 ,4);Serial.println("V" );
return data*LSB*2/1000000;
}else if(data < 0x20000){
data = data - 0x20000;
//Serial.print(data,HEX);Serial.print(" , " );Serial.print(-(-1* data * LSB * 2 /1000000 ),4);Serial.println("V" );
return -(-1*data*LSB*2/1000000);
}
}
void loop() {
//read_range();
float A0data = read_voltdata();
Serial.println(A0data,4);
delay(3000);
}