-
-
Save ElectricImpSampleCode/c6981fcb9e30683ead8b to your computer and use it in GitHub Desktop.
// 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(); |
Hai sir,
I need more information how to read ROM command from Master device in STC15F
You need to write your own 1-Wire driver for that. It will issue the signals to the peripheral device from the STC15F via one if the chip's GPIO pins, eg. https://github.com/qalex/blackboard-STC15/blob/master/DS18B20.c
Commands are sent by the host (Uno) to the peripheral (STC). I don't think the STC will not read 1-Wire natively, so you'll need to write code for the STC that monitors the line and times high and low voltage periods to interpret the signalling. Some general guidance here: https://developer.electricimp.com/resources/onewire#what-is-1-wire
If you only have one peripheral, you can send the Skip ROM command (0xCC
) to ignore device identification. The function awakeAndGetTemp()
above shows the flow. 0x44
is the command to tell the BS18B20 sensor to take a reading (you can emulate this on the STC) and then you do the process again, this time with the 0xBE
command, to receive the reading.
1-Wire is usually used for basic sensor data. If you need to transmit more complex info between the Uno and the STC, use UART.
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:
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!