Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
1-Wire Examples
// FUNCTIONS
function onewireReset() {
// Configure UART for 1-Wire RESET timing
ow.configure(9600, 8, PARITY_NONE, 1, NO_CTSRTS);
ow.write(0xF0);
ow.flush();
local read = ow.read();
if (read == -1) {
// No UART data at all
server.log("No circuit connected to UART.");
return false;
} else if (read == 0xF0) {
// UART RX will read TX if there's no device connected
server.log("No 1-Wire devices are present.");
return false;
} else {
// Switch UART to 1-Wire data speed timing
ow.configure(115200, 8, PARITY_NONE, 1, NO_CTSRTS);
return true;
}
}
function onewireWriteByte(byte) {
for (local i = 0 ; i < 8 ; i++) {
// Run through the bits in the byte, extracting the
// LSB (bit 0) and sending it to the bus
byte = byte >> 1;
onewireBit(byte & 0x01);
}
}
function onewireReadByte() {
local byte = 0;
for (local i = 0 ; i < 8 ; i++) {
// Build up byte bit by bit, LSB first
byte = (byte >> 1) + 0x80 * onewireBit(1);
}
return byte;
}
function onewireBit(bit) {
bit = bit ? 0xFF : 0x00;
ow.write(bit);
ow.flush();
local returnVal = ow.read() == 0xFF ? 1 : 0;
return returnVal;
}
function onewireSearch(nextNode) {
// 'lastForkPoint' records where the device tree last branched
local lastForkPoint = 0;
// Reset the bus and exit if no device found
if (onewireReset()) {
// There are 1-Wire device(s) on the bus, so issue the 1-Wire SEARCH command (0xF0)
onewireWriteByte(0xF0);
// Work along the 64-bit ROM code, bit by bit, from LSB to MSB
for (local i = 64 ; i > 0 ; i--) {
local byte = (i - 1) / 8;
// Read bit from bus
local bit = onewireBit(1);
// Read the next bit
if (onewireBit(1)) {
if (bit) {
// Both bits are 1 which indicates that there are no further devices
// on the bus, so put pointer back to the start and break out of the loop
lastForkPoint = 0;
break;
}
} else if (!bit) {
// First and second bits are both 0: we're at a node
if (nextNode > i || (nextNode != i && (id[byte] & 1))) {
// Take the '1' direction on this point
bit = 1;
lastForkPoint = i;
}
}
// Write the 'direction' bit. For example, if it's 1 then all further
// devices with a 0 at the current ID bit location will go offline
onewireBit(bit);
// Write the bit to the current ID record
id[byte] = (id[byte] >> 1) + 0x80 * bit;
}
}
// Return the last fork point so it can form the start of the next search
return lastForkPoint
}
function onewireDevices() {
id <- [0,0,0,0,0,0,0,0];
nextDevice <- 65;
while (nextDevice) {
nextDevice = onewireSearch(nextDevice);
// Store the device ID discovered by one_wire_search() in an array
// Nb. We need to clone the array, id, so that we correctly save
// each one rather than the address of a single array
peripherals.push(clone(id));
}
}
function getTemp() {
local tempLSB = 0;
local tempMSB = 0;
local tempCelsius = 0;
// Wake up in five seconds for the next reading
imp.wakeup(5.0, getTemp);
// Reset the 1-Wire bus
local result = onewireReset();
if (result) {
// Issue 1-Wire Skip ROM command (0xCC) to select all devices on the bus
onewireWriteByte(0xCC);
// Issue DS18B20 Convert command (0x44) to tell all DS18B20s to get the temperature
// Even if other devices don't ignore this, we will not read them
onewireWriteByte(0x44);
// Wait 750ms for the temperature conversion to finish
imp.sleep(0.75);
foreach (device, peripheralId in peripherals) {
// Run through the list of discovered peripheral devices, getting the temperature
// if a given device is of the correct family number: 0x28 for BS18B20
if (peripheralId[7] == 0x28) {
onewireReset();
// Issue 1-Wire MATCH ROM command (0x55) to select device by ID
onewireWriteByte(0x55);
// Write out the 64-bit ID from the array's eight bytes
for (local i = 7 ; i >= 0 ; i--) {
onewireWriteByte(peripheralId[i]);
}
// Issue the DS18B20's READ SCRATCHPAD command (0xBE) to get temperature
onewireWriteByte(0xBE);
// Read the temperature value from the sensor's RAM
tempLSB = onewireReadByte();
tempMSB = onewireReadByte();
// Signal that we don't need any more data by resetting the bus
onewireReset();
// Calculate the temperature from LSB and MSB, making sure we
// sign-extend the signed 16-bit temperature readinf ('raw')
// to a Squirrel 32-bit signed integer ('tempCelsius')
local raw = (tempMSB << 8) + tempLSB;
tempCelsius = ((raw << 16) >> 16) * 0.0625;
server.log(format("Device: %02d Family: %02x Serial: %02x%02x%02x%02x%02x%02x Temp: %3.2f", (device + 1), peripheralId[7], peripheralId[1], peripheralId[2], peripheralId[3], peripheralId[4], peripheralId[5], peripheralId[6], tempCelsius));
}
}
}
}
// RUNTIME START
// Set up the 1-Wire UART. This is for an imp001 -
// change the UART object in the line below for other imps
ow <- hardware.uart12;
peripherals <- [];
// Enumerate the devices on the bus
onewireDevices();
// Start sampling temperature data
getTemp();
// FUNCTIONS
function onewireReset() {
// Configure UART for 1-Wire RESET timing
ow.configure(9600, 8, PARITY_NONE, 1, NO_CTSRTS);
ow.write(0xF0);
ow.flush();
local read = ow.read();
if (read == -1) {
// No UART data at all
server.log("No circuit connected to UART.");
return false;
} else if (read == 0xF0) {
// UART RX will read TX if there's no device connected
server.log("No 1-Wire devices are present.");
return false;
} else {
// Switch UART to 1-Wire data speed timing
ow.configure(115200, 8, PARITY_NONE, 1, NO_CTSRTS);
return true;
}
}
function onewireWriteByte(byte) {
for (local i = 0 ; i < 8 ; ++i) {
// Run through the bits in the byte, extracting the
// LSB (bit 0) and sending it to the bus
byte = byte >> 1;
onewireBit(byte & 0x01);
}
}
function onewireReadByte() {
local byte = 0;
for (local i = 0 ; i < 8 ; ++i) {
// Build up byte bit by bit, LSB first
byte = (byte >> 1) + 0x80 * onewireBit(1);
}
return byte;
}
function onewireBit(bit) {
bit = bit ? 0xFF : 0x00;
ow.write(bit);
ow.flush();
local returnValue = ow.read() == 0xFF ? 1 : 0;
return returnValue;
}
function awakeAndGetTemp() {
// Wake up every 30 seconds and write to the server
local tempLSB = 0;
local tempMSB = 0;
local tempCelsius = 0;
// Run loop again in 30 seconds
imp.wakeup(30.0, awakeAndGetTemp);
if (onewireReset()) {
onewireWriteByte(0xCC); // 1-Wire Skip ROM command
onewireWriteByte(0x44);
// Wait for at least 750ms for data to be collated
imp.sleep(0.8);
// Get the data
onewireReset();
onewireWriteByte(0xCC); // 1-Wire Skip ROM command
onewireWriteByte(0xBE); // Tell sensor to take a reading
tempLSB = onewireReadByte();
tempMSB = onewireReadByte();
// Reset bus to stop sensor sending unwanted data
onewireReset();
// Calculate the temperature from LSB and MSB, making sure we
// sign-extend the signed 16-bit temperature readinf ('raw')
// to a Squirrel 32-bit signed integer ('tempCelsius')
local raw = (tempMSB << 8) + tempLSB;
tempCelsius = ((raw << 16) >> 16) * 0.0625;
server.log(format("Temperature: %3.2f degrees C", tempCelsius));
}
}
// RUNTIME START
// Set up the 1-Wire UART. This is for an imp001 -
// change the UART object in the line below for other imps
ow <- hardware.uart12;
awakeAndGetTemp();
@mikespolk

This comment has been minimized.

Copy link

@mikespolk mikespolk commented Feb 23, 2021

Thank you for the code example. It is quite clear and helps me to write my customized Python detection routine in Raspberry.
However, I cannot understand the IF clause on line 75:

           // First and second bits are both 0: we're at a node
            if (nextNode > i || (nextNode != i && (id[byte] & 1))) {
                // Take the '1' direction on this point
                bit = 1;
                lastForkPoint = i;
            }        

On that line, it is easy to understand that the direction bit value depends on if the discrepancy in this round appears before or after the bit position during last round. However, why would it ever depend on the LSB bit value (=detected during last round)?

Can you please clarify, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment