Supported and tested Hardware: Attiny84 - Global variables use 574 bytes (112%) of dynamic memory
Closed this issue · 17 comments
Supported and tested Hardware
embedded real life test setup: run test-example, use ds9490-master, arduino 1.8.3, Windows 10 and the board-library named in the brackets
Hi,
I tried to compile using this core ATTinyCore for Attiny84 and the example DS18B20 as thermometer:
Sketch uses 6170 bytes (75%) of program storage space. Maximum is 8192 bytes.
data section exceeds available space in boardGlobal variables use 574 bytes (112%) of dynamic memory, leaving -62 bytes for local variables. Maximum is 512 bytes.Not enough memory; see https://support.arduino.cc/hc/en-us/articles/360013825179 for tips on reducing your footprint.
Error compiling for board ATtiny24/44/84(a) (No bootloader).
Any tips to shorten this code?
I would like to read the TMP117 sensor and send the data as if it were a DS18B20.
Well, you see the example DS18B20_thermometer.ino and it's overhead:
- 3 emulated ds18b20 instead of 1
- uart for debug
- blinking for demo
after removing this I get (for normal arduino, but tiny should be close):
Sketch uses 4576 bytes (14%) of program storage space. Maximum is 30720 bytes.
Global variables use 135 bytes (6%) of dynamic memory, leaving 1913 bytes for local variables. Maximum is 2048 bytes.
So there should be plenty of space left for your tmp117
Hi @orgua ,
Assuming that scratchpad is private, how can I edit these registers in Setup() or Loop()?
I tried using the constructor, but it didn't accept it.
class DS18B20 : public OneWireItem
{
private:
uint8_t scratchpad[9];
void updateCRC(void);
https://github.com/orgua/OneWireHub/blob/main/src/DS18B20.h
DS18B20::DS18B20(uint8_t ID1, uint8_t ID2, uint8_t ID3, uint8_t ID4, uint8_t ID5, uint8_t ID6, uint8_t ID7) : OneWireItem(ID1, ID2, ID3, ID4, ID5, ID6, ID7)
{
scratchpad[0] = 0xA0; // TLSB --> 10 degC as std
scratchpad[1] = 0x00; // TMSB
scratchpad[2] = 0x4B; // THRE --> Trigger register TH
scratchpad[3] = 0x46; // TLRE --> TLow
scratchpad[4] = 0x7F; // Conf
// = 0 R1 R0 1 1 1 1 1 --> R=0 9bit .... R=3 12bit
scratchpad[5] = 0xFF; // 0xFF
scratchpad[6] = 0x00; // Reset
scratchpad[7] = 0x10; // 0x10
updateCRC(); // update scratchpad[8]
ds18s20_mode = (ID1 == 0x10); // different tempRegister
// disable bus-features:
fast_search_rom = false;
}
https://github.com/orgua/OneWireHub/blob/main/src/DS18B20.cpp
I believe I made a mistake, the TMP117 datasheet mentions SCRATCHPAD in the description of EEPROM1 and EEPROM3, but the DS18B20 datasheet says 64-Bit Lasered ROM Code.
What I'm trying to change are the 48-BIT SERIAL NUMBER, contained in the 64-Bit Lasered ROM Code.
ROM Commands
After the bus master has detected a presence pulse, it
can issue a ROM command. These commands operate
on the unique 64-bit ROM codes of each slave device
and allow the master to single out a specific device if
many are present on the 1-Wire bus. These commands
also allow the master to determine how many and what
types of devices are present on the bus or if any device
has experienced an alarm condition. There are five ROM
commands, and each command is 8 bits long. The master
device must issue an appropriate ROM command before
issuing a DS18B20 function command.
Search Rom [F0h]
When a system is initially powered up, the master must
identify the ROM codes of all slave devices on the bus,
which allows the master to determine the number of
slaves and their device types. The master learns the
ROM codes through a process of elimination that requires
the master to perform a Search ROM cycle (i.e., Search
ROM command followed by data exchange) as many
times as necessary to identify all of the slave devices.
If there is only one slave on the bus, the simpler Read
ROM [33h] command can be used in place of the Search
ROM process. For a detailed explanation of the Search
ROM procedure, refer to Application Note 937: Book of
iButton® Standards. After every Search ROM cycle, the
bus master must return to Step 1 (Initialization) in the
transaction sequence.
Read Rom [33h]
This command can only be used when there is one slave
on the bus. It allows the bus master to read the slave’s
64-bit ROM code without using the Search ROM proce-
dure. If this command is used when there is more than
one slave present on the bus, a data collision will occur
when all the slaves attempt to respond at the same time.
Match Rom [55H]
The match ROM command followed by a 64-bit ROM
code sequence allows the bus master to address a
specific slave device on a multidrop or single-drop bus.
Only the slave that exactly matches the 64-bit ROM code
sequence will respond to the function command issued
by the master; all other slaves on the bus will wait for a
reset pulse.
C.3. Search ROM Command
Even if the master does not know the serial numbers of
the devices connected to the 1–Wire bus, it is possible
to address one single device at a time. This is done by
using the command Search ROM, code F0H. This com-
mand acts like Read ROM combined with Match ROM.
All iButtons will sequentially send the true and the false
value of the actual ROM bit during the two Read time
slots following the Search ROM command. If all devices
have a 0 in this bit position, the reading will be 01; if the
bit position contains a 1, the result will be 10. If both, a 1
and a 0 occur in this bit position, reading will result in two
0 bits, indicating a conflict. The master now has to send
the bit value 1 or 0 to select the devices that will remain
in the process of selection. All deselected devices will
be idle until they receive a Reset Pulse. After the first
stage of selection, 63 reading/selecting cycles will fol-
low, until finally the master has learned one device’s
ROM code and simultaneously has addressed it. Each
stage of selection consists of two Read time slots and
one Write time slot. The complete process of learning
and simultaneous addressing is about three times the
length of the Match ROM command, but it allows selec-
tion of all the connected devices sequentially without
knowing the ROM values beforehand. In an application
where the iButtons are fixed in position on the 1–Wire
bus, it is most efficient for the master to evaluate all
ROM contents with the Search ROM command and
then to use the Match ROM command to address spe-
cific devices. If the application requires constant identifi-
cation and communication with new devices as they
come and go, it will be necessary to use the Search
ROM command to identify and address each new part.
Just for reference:
What I'm trying to change are the 48-BIT SERIAL NUMBER, contained in the 64-Bit Lasered ROM Code.
so you don't want the scratchpad but ID1:7 - one of these is the family code the others add up to 48 bit.
As guided in #125,
Alternative Var 1 didn't work (another user said it worked, but it doesn't work if CRC is required).
ds18b20.ID[1] = 0x01;
// Setup OneWire
hub.attach(ds18b20);
DS18B20 emulator:
/*
Example-Code that emulates a DS18B20
Tested with:
- https://github.com/PaulStoffregen/OneWire --> DS18x20-Example, atmega328@16MHz as Slave
- DS9490R-Master, atmega328@16MHz and teensy3.2@96MHz as Slave
*/
#include "OneWireHub.h"
#include "DS18B20.h" // Digital Thermometer, 12bit
constexpr uint8_t pin_led { 13 };
constexpr uint8_t pin_onewire { 8 };
auto hub = OneWireHub(pin_onewire);
auto ds18b20 = DS18B20(DS18B20::family_code, 0x00, 0x00, 0xB2, 0x18, 0xDA, 0x00); // DS18B20: 9-12bit, -55 - +85 degC
bool blinking(void);
void setup()
{
Serial.begin(9600);
Serial.println("OneWire-Hub DS18B20 Temperature-Sensor");
Serial.flush();
pinMode(pin_led, OUTPUT);
ds18b20.ID[1] = 0x01; // <------------------- New serial number
// Setup OneWire
hub.attach(ds18b20);
Serial.print("Test - set Temperatures to 21 degC: ");
const int8_t temperature = 21;
ds18b20.setTemperature(temperature);
Serial.println(ds18b20.getTemperature());
Serial.println("config done");
}
void loop()
{
// following function must be called periodically
hub.poll();
// this part is just for debugging (USE_SERIAL_DEBUG in OneWire.h must be enabled for output)
if (hub.hasError()) hub.printError();
// Blink triggers the state-change
if (blinking())
{
// Set temp
static float temperature = 20.0;
temperature += 0.1;
if (temperature > 30.0) temperature = 20.0;
ds18b20.setTemperature(temperature);
Serial.println(temperature);
}
}
bool blinking(void)
{
constexpr uint32_t interval = 1000; // interval at which to blink (milliseconds)
static uint32_t nextMillis = millis(); // will store next time LED will updated
if (millis() > nextMillis)
{
nextMillis += interval; // save the next time you blinked the LED
static uint8_t ledState = LOW; // ledState used to set the LED
if (ledState == LOW) ledState = HIGH;
else ledState = LOW;
digitalWrite(pin_led, ledState);
return 1;
}
return 0;
}
Tester.ino (modified):
#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
#define TEMPERATURE_PRECISION 9 // Lower resolution
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
int numberOfDevices; // Number of temperature devices found
DeviceAddress tempDeviceAddress; // We'll use this variable to store a found device address
void setup(void)
{
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
// start serial port
Serial.begin(9600);
Serial.println("Dallas Temperature IC Control Library Demo");
}
void initSensors(void) {
// Start up the library
sensors.begin();
// Grab a count of devices on the wire
numberOfDevices = sensors.getDeviceCount();
// locate devices on the bus
Serial.print("Locating devices...");
Serial.print("Found ");
Serial.print(numberOfDevices, DEC);
Serial.println(" devices.");
// report parasite power requirements
Serial.print("Parasite power is: ");
if (sensors.isParasitePowerMode()) Serial.println("ON");
else Serial.println("OFF");
// Loop through each device, print out address
for (int i = 0; i < numberOfDevices; i++)
{
// Search the wire for address
if (sensors.getAddress(tempDeviceAddress, i))
{
Serial.print("Found device ");
Serial.print(i, DEC);
Serial.print(" with address: ");
printAddress(tempDeviceAddress);
Serial.println();
Serial.print("Setting resolution to ");
Serial.println(TEMPERATURE_PRECISION, DEC);
// set the resolution to TEMPERATURE_PRECISION bit (Each Dallas/Maxim device is capable of several different resolutions)
sensors.setResolution(tempDeviceAddress, TEMPERATURE_PRECISION);
Serial.print("Resolution actually set to: ");
Serial.print(sensors.getResolution(tempDeviceAddress), DEC);
Serial.println();
} else {
Serial.print("Found ghost device at ");
Serial.print(i, DEC);
Serial.print(" but could not detect address. Check power and cabling");
}
}
}
// function to print the temperature for a device
void printTemperature(DeviceAddress deviceAddress)
{
// method 1 - slower
//Serial.print("Temp C: ");
//Serial.print(sensors.getTempC(deviceAddress));
//Serial.print(" Temp F: ");
//Serial.print(sensors.getTempF(deviceAddress)); // Makes a second call to getTempC and then converts to Fahrenheit
// method 2 - faster
float tempC = sensors.getTempC(deviceAddress);
if (tempC == DEVICE_DISCONNECTED_C)
{
Serial.println("Error: Could not read temperature data");
return;
}
Serial.print("Temp C: ");
Serial.print(tempC);
Serial.print(" Temp F: ");
Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
}
void loop(void)
{
initSensors();
digitalWrite(13, digitalRead(2));
delay(500);
// call sensors.requestTemperatures() to issue a global temperature
// request to all devices on the bus
Serial.print("Requesting temperatures...");
sensors.requestTemperatures(); // Send the command to get temperatures
// Loop through each device, print out temperature data
for (int i = 0; i < numberOfDevices; i++)
{
// Search the wire for address
if (sensors.getAddress(tempDeviceAddress, i))
{
// Output the device ID
Serial.print("Temperature for device: ");
Serial.println(i, DEC);
// It responds almost immediately. Let's print out the data
printTemperature(tempDeviceAddress); // Use a simple function to print out the data
}
//else ghost device! Check your power requirements and cabling
}
Serial.println("DONE\r\n\r\n");
}
// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
for (uint8_t i = 0; i < 8; i++)
{
if (deviceAddress[i] < 16) Serial.print("0");
Serial.print(deviceAddress[i], HEX);
}
}
If updating the CRC this works:
//Changing ROM serial number
ds18b20.ID[1] = 0x12; // ID1...ID6 (48-BIT SERIAL NUMBER)
// Update CRC after changing ROM serial number
ds18b20.ID[7] = ds18b20.crc8(ds18b20.ID, 7);
// Setup OneWire
hub.attach(ds18b20);
Well, I can't help you with that one. First I don't know what you are trying to accomplish. Second, Var 1 is working for me and you keep the error-description to yourself. But you are right, some masters require a valid crc in ID7.
Your example-code shows that you can just set ID1 during construction (that could also be done in loop()):
DS18B20(ID1, 0x00, 0x00, 0xB2, 0x18, 0xDA, 0x00);
Yes, in loop() it is possible to change the serial number, as long as you remove and add it, it is not necessary to add a new one (As instructed in Var 2 #119)
hub.detach(ds18b20);
ds18b20.ID[1] = new_serial_number++;
ds18b20.ID[7] = ds18b20.crc8(ds18b20.ID, 7);
// Setup OneWire
hub.attach(ds18b20);
Full code:
/*
Example-Code that emulates a DS18B20
Tested with:
- https://github.com/PaulStoffregen/OneWire --> DS18x20-Example, atmega328@16MHz as Slave
- DS9490R-Master, atmega328@16MHz and teensy3.2@96MHz as Slave
*/
#include "OneWireHub.h"
#include "DS18B20.h" // Digital Thermometer, 12bit
constexpr uint8_t pin_led { 13 };
constexpr uint8_t pin_onewire { 8 };
auto hub = OneWireHub(pin_onewire);
auto ds18b20 = DS18B20(DS18B20::family_code, 0x00, 0x00, 0xB2, 0x18, 0xDA, 0x00); // DS18B20: 9-12bit, -55 - +85 degC
bool blinking(void);
uint8_t new_serial_number = 0;
void setup()
{
Serial.begin(9600);
Serial.println("OneWire-Hub DS18B20 Temperature-Sensor");
Serial.flush();
pinMode(pin_led, OUTPUT);
ds18b20.ID[1] = 0x12;
ds18b20.ID[7] = ds18b20.crc8(ds18b20.ID, 7);
// Setup OneWire
hub.attach(ds18b20);
Serial.print("Test - set Temperatures to 21 degC: ");
const int8_t temperature = 21;
ds18b20.setTemperature(temperature);
Serial.println(ds18b20.getTemperature());
Serial.println("config done");
}
void loop()
{
// following function must be called periodically
hub.poll();
// this part is just for debugging (USE_SERIAL_DEBUG in OneWire.h must be enabled for output)
if (hub.hasError()) hub.printError();
// Blink triggers the state-change
if (blinking())
{
hub.detach(ds18b20);
ds18b20.ID[1] = new_serial_number++;
ds18b20.ID[7] = ds18b20.crc8(ds18b20.ID, 7);
// Setup OneWire
hub.attach(ds18b20);
// Set temp
static float temperature = 20.0;
temperature += 0.1;
if (temperature > 30.0) temperature = 20.0;
ds18b20.setTemperature(temperature);
Serial.println(temperature);
}
}
bool blinking(void)
{
constexpr uint32_t interval = 1000; // interval at which to blink (milliseconds)
static uint32_t nextMillis = millis(); // will store next time LED will updated
if (millis() > nextMillis)
{
nextMillis += interval; // save the next time you blinked the LED
static uint8_t ledState = LOW; // ledState used to set the LED
if (ledState == LOW) ledState = HIGH;
else ledState = LOW;
digitalWrite(pin_led, ledState);
return 1;
}
return 0;
}
Var 1 is working for me and you keep the error-description to yourself
There is not much to comment, the master simply does not find the device:
Serial Monitor output from Tester.ino (previously mentioned code):
Wrong CRC:
08:29:06.164 -> Locating devices...Found 0 devices.
08:29:06.197 -> Parasite power is: OFF
08:29:06.661 -> Requesting temperatures...DONE
Correct CRC:
08:30:15.419 -> Locating devices...Found 1 devices.
08:30:15.452 -> Parasite power is: OFF
08:30:15.452 -> Found device 0 with address: 280700B218DA00DD
08:30:15.518 -> Setting resolution to 9
08:30:15.551 -> Resolution actually set to: 9
08:30:16.015 -> Requesting temperatures...Temperature for device: 0
08:30:16.082 -> Temp C: 20.87 Temp F: 69.57
08:30:16.115 -> DONE
This library uses CRC, it's one of the best I've seen for DS18B20:
https://github.com/milesburton/Arduino-Temperature-Control-Library
This library supports the following devices :
DS18B20
DS18S20
DS1822
DS1820
MAX31820
MAX31850
Observation, the tests were done with Arduino UNO/Nano with 16MHz 5V, I still need to test if it works with Attiny85, which is the objective.
Apparently Attiny85 has to run at 8MHz for 3.3V (which is the voltage the Datalogger supplies [3.5V ~ 4.2V from 18650 battery]).
things I consider when you just mention "Var 1 didn't work" without any context (error-description, used hardware, software, setup):
- there is actually an issue with this lib
- your compiler complained
- the ID stayed the same, despite the attempt to change it
- your house burned down
- your ow-master complains
Alright then, good luck with https://github.com/milesburton/Arduino-Temperature-Control-Library
things I consider when you just mention "Var 1 didn't work" without any context (error-description, used hardware, software, setup):
* there is actually an issue with this lib * your compiler complained * the ID stayed the same, despite the attempt to change it * your house burned down * your ow-master complains
Alright then, good luck with https://github.com/milesburton/Arduino-Temperature-Control-Library
About the Arduino-Temperature-Control-Library library, I didn't want to say that it's better than yours, just that it's the best I found to read DS18B20, if your library also reads DS18B20 I haven't tested that part.
I didn't understand some items on your list, can you explain more please?
explanation: I can't look into your head or read between the lines - so I can't help you, sorry.
This issue was strange from the beginning as you completely ignored the issue-presets, including the provided help-sections and requests for context. If you don't take the time, why should I?
It became clear that there is no issue with this lib. So please try to find support in some forum, stackoverflow or chatgpt.
Good luck with your project :)
explanation: I can't look into your head or read between the lines - so I can't help you, sorry. This issue was strange from the beginning as you completely ignored the issue-presets, including the provided help-sections and requests for context. If you don't take the time, why should I?
It became clear that there is no issue with this lib. So please try to find support in some forum, stackoverflow or chatgpt.
Good luck with your project :)
Horrible behavior. Avoid treating people like that.
Where did I step on your toe? Would you like to elaborate?
I put many hours into development and documentation and offer everything free of charge on the internet. Github issues are mainly for bugs in the repo & feature-request and less for end-user support and programming-lessons -> Thats what forums are for.
The issue started with a specific programming-problem without enough context, especially the source-code that was troubling you. I tried to guess and help you since, but you present problem after problem, all programming-related and this thread is now far into offtopic-land.
For 100 $/h I'm happy to write your code or teach you c++.