Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

first implementation of 1-wire protocol #505

Merged
merged 9 commits into from
Apr 22, 2023

Conversation

conejoninja
Copy link
Member

I would like @dn-kolesnikov to review this PR as it was mainly his work, I just adapted it to the proper repo structure.

Once merge, issue #489 could be closed.

@deadprogram
Copy link
Member

Was just looking at this PR. So first of all seems to me that it would be better to structure the files like this:

onewire/onewire.go

And then separately

ds18b20/ds18b20.go

This seems more in keeping with the way things like lora and net are currently.

Future onewire devices (EEPROMs, fuel gauges, etc.) would be added at the root level, like pretty much all of the other drivers are now.

What do you think?

@deadprogram
Copy link
Member

Also, to be in fully correct naming it should be 1-wire not onewire.

Due to Go naming rules this would turn into just wire, correct?

This seems appealing:

package somedevice

import "tinygo.org/x/drivers/1-wire"

func (d *Driver) DoSomething() {
    wire.Reset()
    wire.Write(...)
}

What do you think?

@conejoninja
Copy link
Member Author

I just follow @dn-kolesnikov naming.

NOTE: There's a popular Arduino library called Wire that handles I²C communication, https://www.arduino.cc/reference/en/language/functions/communication/wire/ It might be confusing?

@deadprogram
Copy link
Member

The name of the package here would be 1-wire In any case, I doubt there would be confusion over that particular name in the code.

Regarding the directory organization, I am not really in favor of the proposed structure. How do we proceed?

@conejoninja
Copy link
Member Author

the structure you proposed seems ok to me and make sense. I'll make the changes and uodate the PR

@conejoninja
Copy link
Member Author

conejoninja commented Jan 21, 2023

I updated the package as suggested, renamed the folder to 1-wire , and the package to wire (suggested by the IDE was __wire), then, we are forced to import it as

import (
	"machine"
	"time"
	wire "tinygo.org/x/drivers/1-wire"

	"tinygo.org/x/drivers/ds18b20"
)

It's ok for me.

@dn-kolesnikov
Copy link

Was just looking at this PR. So first of all seems to me that it would be better to structure the files like this:

onewire/onewire.go

And then separately

ds18b20/ds18b20.go

This seems more in keeping with the way things like lora and net are currently.

Future onewire devices (EEPROMs, fuel gauges, etc.) would be added at the root level, like pretty much all of the other drivers are now.

What do you think?

The Arduino standard library is called OneWire (https://www.arduino.cc/reference/en/libraries/onewire/).

@deadprogram
Copy link
Member

@dn-kolesnikov has a good point. We should probably name it onewire.


// SliceToHexString converts a slice to Hex string
// fmt.Printf - compile error on an Arduino Uno boards
func SliceToHexString(rom []uint8) string {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just out of curiosity, what was the reason to not use encoding/hex?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just forgot about it... image

@matveynator
Copy link

Good day ). As each device are using tiny bits of onewire protocol implementation (as I understood - small memory usage wise) it is good that devices are added root level. "onewire" name also seems reasonable... I am also ready to help )

@dn-kolesnikov
Copy link

at the moment I am checking the function of searching for multiple devices on the bus. I had to change the Device structure and add a few additional functions. the next commit to my repository will break compatibility with the current versions of the library. the examples will also be rewritten taking into account the new changes.

@conejoninja
Copy link
Member Author

at the moment I am checking the function of searching for multiple devices on the bus. I had to change the Device structure and add a few additional functions. the next commit to my repository will break compatibility with the current versions of the library. the examples will also be rewritten taking into account the new changes.

Feel free to make the PR directly from your repository. I did it because I needed for a FOSDEM talk, but I started to think it will not be merged on time, no need to rush.

@deadprogram
Copy link
Member

I was actually getting ready to merge this unless there is some reason I shouldn't?

@conejoninja
Copy link
Member Author

I was actually getting ready to merge this unless there is some reason I shouldn't?

well, @dn-kolesnikov commented the next change will break the compatibility, so I guess it's better to wait

@bgould
Copy link
Member

bgould commented Mar 7, 2023

@conejoninja Sounds like @dn-kolesnikov has some new version of this mentioned in #489 ... how should we move forward with this, do you want to merge the changes into your branch or just should @dn-kolesnikov start a new one?

func (d Device) WriteBit(data uint8) {
d.p.Configure(machine.PinConfig{Mode: machine.PinOutput})
if data&1 == 1 { // Send '1'
time.Sleep(5 * time.Microsecond)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the late comment, but I wasn't around in January when this PR was started.

I just want to point out that time.Sleep() yields to the goroutine scheduler. There is no guarantee that this will sleep for 5 microseconds. It could sleep for 100s of microseconds, or several milliseconds.

Since TinyGo does not provide a non-yielding runtime.delayMicros() or machine.delayMicros() function, as far as I know, maybe there is no other option right now.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have conducted several experiments for the chips I have (rp2040, stm32f103, stm32f411, attiny85, atmega328p). Created a project:

package main

import "time"

func main() {
	for {
		time.Sleep(5 * time.Microsecond)
	}
}

Got an assembler listing and studied them. In all variants, a similar tick counting mechanism was used to organize the delay.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's interesting.. Have you looked at the SAMD21? I've been struggling with it. time.Sleep() seems to have an overhead of 250-400 microseconds. The following program prints: elapsed millis: 36621 instead of a number close to 500 milliseconds:

package main

import "time"

func main() {
        time.Sleep(2 * time.Second) // wait for serial monitor

        println("Starting...")
        start := time.Now()

        for i := 0; i < 100_000; i++ {
                time.Sleep(5 * time.Microsecond)
        }

        elapsed := time.Since(start)
        println("elapsed millis:", elapsed.Milliseconds())
}

// Dow-CRC using polynomial X^8 + X^5 + X^4 + X^0
// Tiny 2x16 entry CRC table created by Arjen Lentz
// See http://lentz.com.au/blog/calculating-crc-with-a-tiny-32-entry-lookup-table
crc8_table := [...]uint8{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, is the TinyGo compiler smart enough to store this as a constant in flash, or will it create this on the stack? I guess it's only 32 bytes, so it doesn't matter except maybe on AVR processors. In my experience, a const string was the only way I could guarantee that an array like this would be stored in flash.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The smallest of the AVR ATtiny85 microcontrollers supported in Tinygo has 512 bytes of RAM. If 32 bytes are critical for your project, you can use a fast CRC calculation algorithm for avr in assembler. Or use
const crc8_table string = "\x00\x5E\xBC\xE2\x61\x3F\xDD\x83\xC2\x9C\x7E\x20\xA3\xFD\x1F\x41\x00\x9D\x23\xBE\x46\xDB\x65\xF8\x8C\x11\xAF\x32\xCA\x57\xE9\x74"

@conejoninja conejoninja requested a review from deadprogram April 9, 2023 05:44
@conejoninja
Copy link
Member Author

I think the conversation is going a bit off-topic. We could merge this and make improvements later.

@bxparks
Copy link
Contributor

bxparks commented Apr 9, 2023

I think the conversation is going a bit off-topic. We could merge this and make improvements later.

Sorry about that, I agree.

@deadprogram
Copy link
Member

OK based on the last comments I am squash/merging. Thank you very much everyone who worked on this!

@deadprogram deadprogram merged commit 5cc2132 into tinygo-org:dev Apr 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants