Add MCP3008 I/O Expander (#1057)

* Add MCP3008

* Fixed Travis build issues

* Travis Build Fix

* Fix Travis foramt issues

* Travis fixes

* Code review changes

* Fix bit shift. off by one and selecting wrong pin

* general fixes

* lint

Co-authored-by: Guillermo Ruffino <glm.net@gmail.com>
This commit is contained in:
SenexCrenshaw 2020-06-14 21:42:46 -04:00 committed by GitHub
parent 35078fd52f
commit 9632ac0e02
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 140 additions and 0 deletions

View file

@ -0,0 +1,23 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import spi
from esphome.const import CONF_ID
DEPENDENCIES = ['spi']
AUTO_LOAD = ['sensor']
MULTI_CONF = True
CONF_MCP3008 = 'mcp3008'
mcp3008_ns = cg.esphome_ns.namespace('mcp3008')
MCP3008 = mcp3008_ns.class_('MCP3008', cg.Component, spi.SPIDevice)
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_id(MCP3008),
}).extend(spi.spi_device_schema(CS_PIN_required=True))
def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
yield cg.register_component(var, config)
yield spi.register_spi_device(var, config)

View file

@ -0,0 +1,52 @@
#include "mcp3008.h"
#include "esphome/core/log.h"
namespace esphome {
namespace mcp3008 {
static const char *TAG = "mcp3008";
float MCP3008::get_setup_priority() const { return setup_priority::HARDWARE; }
void MCP3008::setup() {
ESP_LOGCONFIG(TAG, "Setting up mcp3008");
this->spi_setup();
}
void MCP3008::dump_config() {
ESP_LOGCONFIG(TAG, "MCP3008:");
LOG_PIN(" CS Pin: ", this->cs_);
}
float MCP3008::read_data_(uint8_t pin) {
byte data_msb = 0;
byte data_lsb = 0;
byte command = ((0x01 << 7) | // start bit
((pin & 0x07) << 4)); // channel number
this->enable();
this->transfer_byte(0x01);
data_msb = this->transfer_byte(command) & 0x03;
data_lsb = this->transfer_byte(0x00);
this->disable();
int data = data_msb << 8 | data_lsb;
return data / 1024.0f;
}
MCP3008Sensor::MCP3008Sensor(MCP3008 *parent, std::string name, uint8_t pin)
: PollingComponent(1000), parent_(parent), pin_(pin) {
this->set_name(name);
}
void MCP3008Sensor::setup() { LOG_SENSOR("", "Setting up MCP3008 Sensor '%s'...", this); }
void MCP3008Sensor::update() {
float value_v = this->parent_->read_data_(pin_);
this->publish_state(value_v);
}
} // namespace mcp3008
} // namespace esphome

View file

@ -0,0 +1,42 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/core/esphal.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/spi/spi.h"
namespace esphome {
namespace mcp3008 {
class MCP3008Sensor;
class MCP3008 : public Component,
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_LEADING,
spi::DATA_RATE_1MHZ> { // At 3.3V 2MHz is too fast 1.35MHz is about right
public:
MCP3008() = default;
void setup() override;
void dump_config() override;
float get_setup_priority() const override;
protected:
float read_data_(uint8_t pin);
friend class MCP3008Sensor;
};
class MCP3008Sensor : public PollingComponent, public sensor::Sensor {
public:
MCP3008Sensor(MCP3008 *parent, std::string name, uint8_t pin);
void setup() override;
void update() override;
protected:
MCP3008 *parent_;
uint8_t pin_;
};
} // namespace mcp3008
} // namespace esphome

View file

@ -0,0 +1,23 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import sensor
from esphome.const import CONF_ID, CONF_NUMBER, CONF_NAME
from . import mcp3008_ns, MCP3008
DEPENDENCIES = ['mcp3008']
MCP3008Sensor = mcp3008_ns.class_('MCP3008Sensor', sensor.Sensor, cg.PollingComponent)
CONF_MCP3008_ID = 'mcp3008_id'
CONFIG_SCHEMA = sensor.SENSOR_SCHEMA.extend({
cv.GenerateID(): cv.declare_id(MCP3008Sensor),
cv.GenerateID(CONF_MCP3008_ID): cv.use_id(MCP3008),
cv.Required(CONF_NUMBER): cv.int_,
}).extend(cv.polling_component_schema('1s'))
def to_code(config):
parent = yield cg.get_variable(config[CONF_MCP3008_ID])
var = cg.new_Pvariable(config[CONF_ID], parent, config[CONF_NAME], config[CONF_NUMBER])
yield cg.register_component(var, config)