neuoy / OneWireArduinoSlave

An arduino library to communicate using the Dallas one-wire protocol, where the Arduino takes the role of a slave. Entirely implemented using interrupts, you can perform other tasks while communication is handled in background.
58 stars 19 forks source link

ATTiny85 Compatibility #1

Closed iinnovations closed 7 years ago

iinnovations commented 9 years ago

Hello,

What registers should be changed to make this code compatible with ATTiny85? It seems as though many do not exist that exist on the ATMega328 target. From the datasheet, there appear to be analogues.

Thanks, Colin

neuoy commented 9 years ago

You'll need to setup two kinds of interrupts : pin change (on the 1-wire data pin), and the timer (that is used to detect timeouts).

The pin change interrupt seems to be explained here for the ATtiny : http://thewanderingengineer.com/2014/08/11/pin-change-interrupts-on-attiny85/

For the timer interrupt, you'll need to understand what is the frequency, how it can be divided if it's too high, and calculate how many ticks you need for the desired delay. It is very likely that you'll need adapt the code to match the ATtiny characteristics, because the current timer code is specific to the Arduino Uno and its processor.

You may also run into fine timing issues, if instructions are not executed at the same speed on the ATtiny, or maybe everything will be fine, I can't say without testing (and I can't test without hardware, and I don't have time right know anyway).

Good luck with the port if you decide to try it, let me know if you can make it work :-)

iinnovations commented 9 years ago

Hello again,

How do I set up a response for another byte command, such as a read scratchpad 0xBE ?

Thanks, Colin

On 9/1/2015 12:51 PM, Youen wrote:

You'll need to setup two kinds of interrupts : pin change (on the 1-wire data pin), and the timer (that is used to detect timeouts).

The pin change interrupt seems to be explained here for the ATtiny : http://thewanderingengineer.com/2014/08/11/pin-change-interrupts-on-attiny85/

For the timer interrupt, you'll need to understand what is the frequency, how it can be divided if it's too high, and calculate how many ticks you need for the desired delay. It is very likely that you'll need adapt the code to match the ATtiny characteristics, because the current timer code is specific to the Arduino Uno and its processor.

You may also run into fine timing issues, if instructions are not executed at the same speed on the ATtiny, or maybe everything will be fine, I can't say without testing (and I can't test without hardware, and I don't have time right know anyway).

Good luck with the port if you decide to try it, let me know if you can make it work :-)

— Reply to this email directly or view it on GitHub https://github.com/neuoy/OneWireArduinoSlave/issues/1#issuecomment-136839751.

neuoy commented 8 years ago

I've modified the sample sketch that is now an implementation of a DS18B20 temperature sensor, which is a more complete example to demonstrate how to use the library. Hope this helps.

By the way, did you manage to make it work on an ATTiny85?

palsbo commented 8 years ago

Hi I am trying to get it to work with ATtiny85 but no luck. I understand for your first answer, that two interrupts has to be implemented, but how? Is it a change in LowLevel.h ? Sorry for my lack of experience - I am lerning :)

neuoy commented 8 years ago

Hi,

I'm afraid you're not picking an easy task for learning. Just a bit of warning because you might not realize what's ahead on this path, so maybe this can avoid you a lot of frustration. I'm assuming you are a beginner in electronics and programming here, so you can mostly ignore the whole post if it's not the case.

You should maybe play a little bit with interrupts on very simple applications before trying to do something as "complicated" (everything is relative though) as 1-wire communication. For example, toggle a LED on/off in an interrupt handler when you detect a state change on a pin. Then toggle a LED on/off at a fixed frequency using a timer interrupt. If you correctly implement these examples using interrupts only, then they should work without any code at all in the main loop (and of course they'll work as well if you make a lot of other unrelated stuff in the main loop). You'll have to look at documentation or tutorials targeting your microcontroller/board to find out how to use interrupts on it.

Once you're acquainted with interrupts on your specific board, then you can try to use them in a more complicated (and useful) applications, such as 1-wire communication, but be warned that debugging such an application is quite painful. If anything goes wrong, you'll have no clue what it is, and you can't use serial console to print debug messages, because it is way too slow compared to 1-wire, so by the time you send any message, you've already missed all the remaining 1-wire communication. Basically, either you're lucky and it works on the first try (unlikely), or you'll need a numeric oscilloscope to observe what is happening on your wires. The remaining option involves a lot of trial and error which could ultimately disgust you of electronics and programming, while there are so much funnier things you could do instead.

Now, to answer your original question, the timer interrupt is implemented in OneWireSlave.cpp, look for ISR(TIMER1_COMPA_vect), this is the code that executes when the timer fires. The timer is configured in function setTimerEvent_, this is probably code that you'll need to modify, as well as the initial setup in the begin function. All that code would ideally not be in OneWireSlave.cpp but abstracted in an external timer library (actually, there are probably existing ones out there, I didn't take the time to search).

For pin state change interrupts, they are currently implemented in LowLevel.h, look for attachInterrupt and detachInterrupt. I never looked at the Attiny85, so I don't have a clue what you will need to change or what you can keep as-is.

You might also have timing issues since your microcontroller may run faster or slower than mine, and sometimes a few microseconds is enough to miss something, and being too fast can be just as bad. The 1-wire protocol uses a lot of fixed time deltas since there is no clock wire, so if you're not inside the tolerance margin it just won't work, and finding out where it fails can be tricky.

If you can get it to work, and are willing to contribute your code, I'll be happy to integrate it in the library (just send me a pull request). Good luck :)

palsbo commented 8 years ago

Hi Youen

Thank you for your quick and comprehensive response.

Well I am a newbie in C++, but I have worked with microprocessors for the last 40 years!! (not as a professional), and I am fully familiar with interrupts as such;

I have made an implementation of a onewire slave protocol on an Arduino Nano presenting a new family code with its own fields and values (code attached in zip-file). This implementation also includes reading distance from a SRF02 as an I2C device. (The application calculate the amount of fuel oil in the tank based on the size and form of the tank, and return the actual fuel volume via the Arduino onewire slave. See the result here: http://owhouse.com. This implementation also required changes to OWFS).

The code in my implementation is very much the same as yours (may be it origins from you!!). I also located the problem to the attachInterrupt in LowLevel.h but failed to make useful modifications.

I grabbed some other code (attached) on the net that runs on the ATtiny85 but my limited C++ experience is not enough to combine the two.

The problem with that code is, that it is not modular enough to be the base for my own implementation.

I have to spend some more time on the problem, but thanks for your help.

Best regards Erik

------ Original Message ------ From: "Youen" notifications@github.com To: "neuoy/OneWireArduinoSlave" OneWireArduinoSlave@noreply.github.com Cc: "palsbo" erik@palsbo.com Sent: 06-02-2016 10:48:25 Subject: Re: [OneWireArduinoSlave] ATTiny85 Compatibility (#1)

Hi,

I'm afraid you're not picking an easy task for learning. Just a bit of warning because you might not realize what's ahead on this path, so maybe this can avoid you a lot of frustration. I'm assuming you are a beginner in electronics and programming here, so you can mostly ignore the whole post if it's not the case.

You should maybe play a little bit with interrupts on very simple applications before trying to do something as "complicated" (everything is relative though) as 1-wire communication. For example, toggle a LED on/off in an interrupt handler when you detect a state change on a pin. Then toggle a LED on/off at a fixed frequency using a timer interrupt. If you correctly implement these examples using interrupts only, then they should work without any code at all in the main loop (and of course they'll work as well if you make a lot of other unrelated stuff in the main loop). You'll have to look at documentation or tutorials targeting your microcontroller/board to find out how to use interrupts on it.

Once you're acquainted with interrupts on your specific board, then you can try to use them in a more complicated (and useful) applications, such as 1-wire communication, but be warned that debugging such an application is quite painful. If anything goes wrong, you'll have no clue what it is, and you can't use serial console to print debug messages, because it is way too slow compared to 1-wire, so by the time you send any message, you've already missed all the remaining 1-wire communication. Basically, either you're lucky and it works on the first try (unlikely), or you'll need a numeric oscilloscope to observe what is happening on your wires. The remaining option involves a lot of trial and error which could ultimately disgust you of electronics and programming, while there are so much funnier things you could do instead.

Now, to answer your original question, the timer interrupt is implemented in OneWireSlave.cpp, look for ISR(TIMER1_COMPAvect), this is the code that executes when the timer fires. The timer is configured in function setTimerEvent, this is probably code that you'll need to modify, as well as the initial setup in the begin function. All that code would ideally not be in OneWireSlave.cpp but abstracted in an external timer library (actually, there are probably existing ones out there, I didn't take the time to search).

For pin state change interrupts, they are currently implemented in LowLevel.h, look for attachInterrupt and detachInterrupt. I never looked at the Attiny85, so I don't have a clue what you will need to change or what you can keep as-is.

You might also have timing issues since your microcontroller may run faster or slower than mine, and sometimes a few microseconds is enough to miss something, and being too fast can be just as bad. The 1-wire protocol uses a lot of fixed time deltas since there is no clock wire, so if you're not inside the tolerance margin it just won't work, and finding out where it fails can be tricky.

If you can get it to work, and are willing to contribute your code, I'll be happy to integrate it in the library (just send me a pull request). Good luck :)

— Reply to this email directly or view it on GitHub.

iinnovations commented 8 years ago

Skip the attiny and go with a 328p. Google Moat 1wire or moat owfs.

C

On Feb 6, 2016, at 3:32 AM, palsbo notifications@github.com wrote:

Hi Youen

Thank you for your quick and comprehensive response.

Well I am a newbie in C++, but I have worked with microprocessors for the last 40 years!! (not as a professional), and I am fully familiar with interrupts as such;

I have made an implementation of a onewire slave protocol on an Arduino Nano presenting a new family code with its own fields and values (code attached in zip-file). This implementation also includes reading distance from a SRF02 as an I2C device. (The application calculate the amount of fuel oil in the tank based on the size and form of the tank, and return the actual fuel volume via the Arduino onewire slave. See the result here: http://owhouse.com. This implementation also required changes to OWFS).

The code in my implementation is very much the same as yours (may be it origins from you!!). I also located the problem to the attachInterrupt in LowLevel.h but failed to make useful modifications.

I grabbed some other code (attached) on the net that runs on the ATtiny85 but my limited C++ experience is not enough to combine the two.

The problem with that code is, that it is not modular enough to be the base for my own implementation.

I have to spend some more time on the problem, but thanks for your help.

Best regards Erik

------ Original Message ------ From: "Youen" notifications@github.com To: "neuoy/OneWireArduinoSlave" OneWireArduinoSlave@noreply.github.com Cc: "palsbo" erik@palsbo.com Sent: 06-02-2016 10:48:25 Subject: Re: [OneWireArduinoSlave] ATTiny85 Compatibility (#1)

Hi,

I'm afraid you're not picking an easy task for learning. Just a bit of warning because you might not realize what's ahead on this path, so maybe this can avoid you a lot of frustration. I'm assuming you are a beginner in electronics and programming here, so you can mostly ignore the whole post if it's not the case.

You should maybe play a little bit with interrupts on very simple applications before trying to do something as "complicated" (everything is relative though) as 1-wire communication. For example, toggle a LED on/off in an interrupt handler when you detect a state change on a pin. Then toggle a LED on/off at a fixed frequency using a timer interrupt. If you correctly implement these examples using interrupts only, then they should work without any code at all in the main loop (and of course they'll work as well if you make a lot of other unrelated stuff in the main loop). You'll have to look at documentation or tutorials targeting your microcontroller/board to find out how to use interrupts on it.

Once you're acquainted with interrupts on your specific board, then you can try to use them in a more complicated (and useful) applications, such as 1-wire communication, but be warned that debugging such an application is quite painful. If anything goes wrong, you'll have no clue what it is, and you can't use serial console to print debug messages, because it is way too slow compared to 1-wire, so by the time you send any message, you've already missed all the remaining 1-wire communication. Basically, either you're lucky and it works on the first try (unlikely), or you'll need a numeric oscilloscope to observe what is happening on your wires. The remaining option involves a lot of trial and error which could ultimately disgust you of electronics and programming, while there are so much funnier things you could do instead.

Now, to answer your original question, the timer interrupt is implemented in OneWireSlave.cpp, look for ISR(TIMER1_COMPAvect), this is the code that executes when the timer fires. The timer is configured in function setTimerEvent, this is probably code that you'll need to modify, as well as the initial setup in the begin function. All that code would ideally not be in OneWireSlave.cpp but abstracted in an external timer library (actually, there are probably existing ones out there, I didn't take the time to search).

For pin state change interrupts, they are currently implemented in LowLevel.h, look for attachInterrupt and detachInterrupt. I never looked at the Attiny85, so I don't have a clue what you will need to change or what you can keep as-is.

You might also have timing issues since your microcontroller may run faster or slower than mine, and sometimes a few microseconds is enough to miss something, and being too fast can be just as bad. The 1-wire protocol uses a lot of fixed time deltas since there is no clock wire, so if you're not inside the tolerance margin it just won't work, and finding out where it fails can be tricky.

If you can get it to work, and are willing to contribute your code, I'll be happy to integrate it in the library (just send me a pull request). Good luck :)

— Reply to this email directly or view it on GitHub.

— Reply to this email directly or view it on GitHub.

neuoy commented 7 years ago

I've merged the work from @ntruchsess that I believe should make the library compatible with ATTiny85, but I can't test it because I don't have one. Let me know if it doesn't fix your problem so I reopen the issue.