この記事は、MIDI&Audioをは無関係です。
Adafruit MCP9808は高精度な温度計です。インターフェースはI2Cです。 このモジュールをRaspberry Pi Zeroに接続し、WiringPiライブラリを使って動作させます。
物理的な接続は基本的に4本です。電源2本をI2Cのデータ(SDA)とクロック(SCL)を接続します。
プログラムをGithubに置きました。
// main.cpp #include <stdio.h> #include <stdint.h> #include "Wiringpi_MCP9808.h" #include <wiringPi.h> int main() { // Make sure the sensor is found, you can also pass in a different i2c // address with tempsensor.begin(0x19) for example, also can be left in blank for default address use // Also there is a table with all addres possible for this sensor, you can connect multiple sensors // to the same i2c bus, just configure each sensor with a different address and define multiple objects for that // A2 A1 A0 address // 0 0 0 0x18 this is the default address // 0 0 1 0x19 // 0 1 0 0x1A // 0 1 1 0x1B // 1 0 0 0x1C // 1 0 1 0x1D // 1 1 0 0x1E // 1 1 1 0x1F Wiringpi_MCP9808 mcp9808; bool result = mcp9808.init(MCP9808_I2CADDR_DEFAULT); if(result){ fprintf(stderr,"Success to create the interface for MCP9808\n"); } else { fprintf(stderr,"Fale to create the interface for MCP9808\n"); } // sets the resolution mode of reading, the modes are defined in the table bellow: // Mode Resolution SampleTime // 0 0.5°C 30 ms // 1 0.25°C 65 ms // 2 0.125°C 130 ms // 3 0.0625°C 250 ms mcp9808.write8(MCP9808_REG_RESOLUTION, 3); //Set Resolution fprintf(stderr,"Resolution = %d\n",mcp9808.read8(MCP9808_REG_RESOLUTION)); //Read Resolution while(1){ mcp9808.wake_shutdown(true); fprintf(stderr,"%5.2f *C\n",mcp9808.readTempC()); mcp9808.wake_shutdown(false); delay(1000); } }
/* * Wiringpi_MCP9808.h * MCP9808 for using WiringPi * by MikataHara * 2024.10.22 */ #include <wiringPiI2C.h> #ifndef _WIRINGPI_MCP9808_H #define _WIRINGPI_MCP9808_H #define MCP9808_I2CADDR_DEFAULT 0x18 ///< I2C address #define MCP9808_REG_CONFIG 0x01 ///< MCP9808 config register #define MCP9808_REG_CONFIG_SHUTDOWN 0x0100 ///< shutdown config #define MCP9808_REG_CONFIG_CRITLOCKED 0x0080 ///< critical trip lock #define MCP9808_REG_CONFIG_WINLOCKED 0x0040 ///< alarm window lock #define MCP9808_REG_CONFIG_INTCLR 0x0020 ///< interrupt clear #define MCP9808_REG_CONFIG_ALERTSTAT 0x0010 ///< alert output status #define MCP9808_REG_CONFIG_ALERTCTRL 0x0008 ///< alert output control #define MCP9808_REG_CONFIG_ALERTSEL 0x0004 ///< alert output select #define MCP9808_REG_CONFIG_ALERTPOL 0x0002 ///< alert output polarity #define MCP9808_REG_CONFIG_ALERTMODE 0x0001 ///< alert output mode #define MCP9808_REG_UPPER_TEMP 0x02 ///< upper alert boundary #define MCP9808_REG_LOWER_TEMP 0x03 ///< lower alert boundery #define MCP9808_REG_CRIT_TEMP 0x04 ///< critical temperature #define MCP9808_REG_AMBIENT_TEMP 0x05 ///< ambient temperature #define MCP9808_REG_MANUF_ID 0x06 ///< manufacture ID #define MCP9808_REG_DEVICE_ID 0x07 ///< device ID #define MCP9808_REG_RESOLUTION 0x08 ///< resolutin /* Class for MCP9808 Temp Sensor */ #define NAN -1 class Wiringpi_MCP9808 { public: Wiringpi_MCP9808(){} bool init(uint8_t addr); void write16(uint8_t reg, uint16_t val); uint16_t read16(uint8_t reg); void write8(uint8_t reg, uint8_t val); uint8_t read8(uint8_t reg); void setResolution(uint8_t value); void wake_shutdown(bool sw); private: uint8_t _i2caddr; }; #endif
(注)16ビットのRead/Writeの関数では、LSB Firstのuint16_tの値をMSB Firstに変換しています。 Raspberry Pi上はLSB First、I2CはMSB FIrstで扱う為、変換する必要があります。 swapBytesはChatGPTを参考に記載しています。
/* * Wiringpi_MCP9808.cpp * Modified for Trinket by MikataHara * 2024.10.19 */ #include <stdint.h> #include <stdio.h> #include "Wiringpi_MCP9808.h" // LSBとMSBを交換 uint16_t swapBytes(uint16_t num) { return ((num&0xFF00) >> 8) | ((num << 8)&0xFF00); } /* Initialize */ bool Wiringpi_MCP9808::init(uint8_t addr) { uint16_t manuf_id, device_id; _i2caddr = wiringPiI2CSetup (addr); fprintf(stderr,"_i2caddr=%d\n",_i2caddr); if (_i2caddr > 0){ manuf_id = read16(MCP9808_REG_MANUF_ID); device_id = read16(MCP9808_REG_DEVICE_ID); fprintf(stderr,"MCP9808_REG_MANUF_ID=%04x\n",manuf_id); fprintf(stderr,"MCP9808_REG_DEVICE_ID=%04x\n",device_id); if (manuf_id != 0x0054) return false; if (device_id != 0x0400) return false; write16(MCP9808_REG_CONFIG, 0x0); } else { return false; } return true; } void Wiringpi_MCP9808::write8(uint8_t reg, uint8_t val){ wiringPiI2CWriteReg8 (_i2caddr, reg, val); } uint8_t Wiringpi_MCP9808::read8(uint8_t reg){ uint16_t result = wiringPiI2CReadReg8 (_i2caddr,reg); return result; } void Wiringpi_MCP9808::write16(uint8_t reg, uint16_t val){ wiringPiI2CWriteReg16 (_i2caddr, reg, swapBytes(val)); } uint16_t Wiringpi_MCP9808::read16(uint8_t reg){ uint16_t result = wiringPiI2CReadReg16 (_i2caddr,reg); return swapBytes(result); } /* Read Temperature */ float Wiringpi_MCP9808::readTempC() { float temp = NAN; uint16_t t = read16(MCP9808_REG_AMBIENT_TEMP); if (t != 0xFFFF) { temp = t & 0x0FFF; temp /= 16.0; if (t & 0x1000) temp -= 256; } return temp; } /* Wakeup and Shutdown */ /* true : wake */ /* false : shutdown */ void Wiringpi_MCP9808::wake_shutdown(bool sw) { uint16_t conf_shutdown; uint16_t conf_register = read16(MCP9808_REG_CONFIG); if (sw == true) { conf_shutdown = conf_register | MCP9808_REG_CONFIG_SHUTDOWN; write16(MCP9808_REG_CONFIG, conf_shutdown); } else if (sw == false) { conf_shutdown = conf_register & ~MCP9808_REG_CONFIG_SHUTDOWN; write16(MCP9808_REG_CONFIG, conf_shutdown); } }