Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
imp006 Breakout Kit Example Code: sensor and Grove display
// IMPORTS
// Get the temperature sensor library
#require "HTS221.device.lib.nut:2.0.2"
// CLASSES
// The following driver class and enum provides support
// for the TM1637 display chip
enum TM1637_LED_CLASS {
ADDR_AUTO = 0x40,
CMD_SET_ADDR = 0xC0,
CMD_DISP_CTRL = 0x88,
// Character constants
BLANK_CHAR = 16,
MINUS_CHAR = 17,
DEGREE_CHAR = 18,
CHAR_COUNT = 19,
// Display specific constants
LED_MAX_ROWS = 4
}
/**
* Hardware driver for Seeed Grove 4-digit LED.
*
* Availibility Device
* @author Tony Smith (@smittytone)
* @license MIT
*
* @class
*
*/
class TM1637 {
/**
* @property {string} VERSION - The library version
*
*/
static VERSION = "1.0.0";
// *********** Private Properties **********
_digits = null;
_buffer = null;
_clk = null;
_dio = null;
_brightness = 2;
_showColon = false;
/**
* Initialize the segment LED
*
* @constructor
*
* @param {imp::hardwar::pin} dataPin - The imp pin connected to Grove WHITE
* @param {imp::hardwar::pin} clockPin - The imp pin connected to Grove YELLOW
*
* @returns {instance} The instance
*
*/
constructor(dataPin, clockPin) {
// 'dataPin' and 'clockPin' are the imp API hardware.pin
// objects connected to, respectively, the Grove white and
// yellow lines. We set these initally LOW
_clk = clockPin;
_dio = dataPin;
_clk.configure(DIGITAL_OUT, 0);
_dio.configure(DIGITAL_OUT, 0);
// _buffer stores the character matrix values for each row of the display
//
// buffer index 0 1 2 3
// [ ] [ ] [ ] [ ]
// character - - . - -
// [ ] [ ] . [ ] [ ]
_buffer = blob(TM1637_LED_CLASS.LED_MAX_ROWS);
// '_digits' stores character matrices for 0-9, A-F, blank and minus
_digits = "\x3F\x06\x5B\x4F\x66\x6D\x7D\x07\x7F\x6F"; // 0-9
_digits += "\x5F\x7C\x58\x5E\x7B\x71"; // A-F
_digits += "\x00\x40\x63"; // Space, minus, degree signs
}
/**
* Clear each row in the segment LED buffer. Requires 'display()' to be called
*
* @returns {instance} this
*
*/
function clear() {
for (local i = 0 ; i < TM1637_LED_CLASS.LED_MAX_ROWS ; i++) {
_buffer[i] = TM1637_LED_CLASS.BLANK_CHAR;
}
return this;
}
/**
* Set the specified segment LED buffer row to a given numeric character. Requires 'display()'
*
* @param {integer} [digit] - The display digit to be written to (0 - 4)
* @param {integer} [number] - The integer required (0 - 16, 0x00 - 0x0F)
*
* @returns {intance} this
*
*/
function writeNumber(digit, number) {
if (digit < 0 || digit >= TM1637_LED_CLASS.LED_MAX_ROWS) return null;
if (number < 0 || number > 15) return null;
_buffer[digit] = _digits[number];
return this;
}
/**
* Set or unset the segment LED display's central colon symbol
*
* @param {bool} [showColon] - Whether the central colon should be lit. Default: true
*
* @returns {instance} this
*
*/
function setColon(set = true) {
if (typeof set != "bool") set = true;
_showColon = set;
return this;
}
/**
* Write the segment LED buffer to the display
*
*/
function display() {
// Signal the start of data
_start();
_writeByte(TM1637_LED_CLASS.ADDR_AUTO);
_stop();
// Signal the data
_start();
_writeByte(TM1637_LED_CLASS.CMD_SET_ADDR);
for (local i = 0 ; i < TM1637_LED_CLASS.LED_MAX_ROWS ; i++) {
_writeByte(_buffer[i] + (_showColon ? 0x80 : 0x00));
}
_stop();
// Tell the display to update
_start();
_writeByte(TM1637_LED_CLASS.CMD_DISP_CTRL + _brightness);
_stop();
}
// *********** Private Functions **********
/**
* Write a single byte to the display
*
* @param {int} data — The 8-bit value to write
*
* @returns {int} The ACK value
*
* @private
*
*/
function _writeByte(data) {
// Write a single byte to the display, signalling its bits
// LSB first out on the line
data = data & 0xFF;
for (local i = 0 ; i < 8 ; i++) {
_clk.write(0);
_dio.write(data & 0x01 ? 1 : 0);
data = data >> 1;
_clk.write(1);
}
// What follows is the signalling required by the TM1637
_clk.write(0);
_dio.write(1);
_clk.write(1);
_dio.configure(DIGITAL_IN);
_delay();
local ack = _dio.read();
if (ack == 0) _dio.configure(DIGITAL_OUT, 0);
_delay();
_dio.configure(DIGITAL_OUT, 0);
_delay();
// Return whether the data was ACK'd
return ack;
}
/**
* Delay for 50 microseconds
*
* @private
*
*/
function _delay() {
imp.sleep(0.00005);
}
/**
* Send START signal (both pins go low)
*
* @private
*
*/
function _start() {
_clk.write(1);
_dio.write(1);
_dio.write(0);
_clk.write(0);
}
/**
* Send STOP signal (both pins go high)
*
* @private
*
*/
function _stop() {
_clk.write(0);
_dio.write(0);
_clk.write(1);
_dio.write(1);
}
}
// GLOBALS
// Set up our global variables, 'sensor' and 'led'
// Configure the sensor's I2C bus
hardware.i2cLM.configure(CLOCK_SPEED_400_KHZ);
// Instantiate a sensor object and set its operational mode
sensor <- HTS221(hardware.i2cLM);
sensor.setMode(HTS221_MODE.ONE_SHOT);
// Instantiate a TM1637 display object on the inner Grove connectpr
led <- TM1637(hardware.pinU, hardware.pinT);
// This function is the core loop: it runs every second, taking a
// reading and displaying the temperature on the LED. For details
// of the 'read()' function, see the HTS221 library doc in the Dev Center:
// https://developer.electricimp.com/libraries/hardware/hts221
function loop() {
// Get and display the reading
sensor.read(function(reading) {
if (!("error" in reading)) {
local tempString = format("%0.1f", reading.temperature);
local tempParts = split(tempString, ".");
// The first three digits show the temperature
// (we use the colon for a decimal point)
led.writeNumber(0, tempParts[0][0].tointeger() - '0');
led.writeNumber(1, tempParts[0][1].tointeger() - '0');
led.writeNumber(2, tempParts[1][0].tointeger() - '0');
// Set final digit as c for Celsius and trigger the display
led.writeNumber(3, 12);
led.setColon().display();
}
});
// Call the loop function again in 1 second
imp.wakeup(1.0, loop);
}
// Power the Grove connectors
hardware.pinXU.configure(DIGITAL_OUT, 1);
// Start the sensor reading loop
loop();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment