# RefValue errors with LibSerialPort

**URL:** <https://discourse.julialang.org/t/refvalue-errors-with-libserialport/49049>\
**Category:** General Usage\
**Tags:** question, error\
**Created:** [October 26, 2020, 2:55pm UTC](https://discourse.julialang.org/t/refvalue-errors-with-libserialport/49049 "2020-10-26T14:55:14Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)\
**Post date:** [October 26, 2020, 2:55pm UTC](https://discourse.julialang.org/t/refvalue-errors-with-libserialport/49049/1 "2020-10-26T14:55:14Z")

</div>

I’m honestly not sure if this has something to do with `LibSerialPort` or if it’s just me, hence the Discourse post as opposed to an issue…

I’m repeatedly reading off of a serial port inside an async loop, and while trying to write to the same port things get stuck (I’m controlling this from `WGLMakie`). If I look into that async task, I get this:

```julia
Task (failed) @0x00007f72b4851ae0
TaskFailedException:
InterruptException:
Stacktrace:
 [1] RefValue at ./refvalue.jl:8 [inlined]
 [2] Ref at ./refpointer.jl:96 [inlined]
 [3] read(::SerialPort, ::Type{UInt8}) at /home/yakir/.julia/packages/LibSerialPort/Ukfil/src/high-level-api.jl:340
 [4] decode(::SerialPort) at /home/yakir/.julia/packages/COBS/05DPe/src/COBS.jl:108
 [5] (::var"#1#2"{Arduino})() at /home/yakir/.julia/dev/SimpleFanControl/src/simpler.jl:65
 [6] lock(::var"#1#2"{Arduino}, ::ReentrantLock) at ./lock.jl:161
 [7] sample!(::Arduino) at /home/yakir/.julia/dev/SimpleFanControl/src/simpler.jl:63
 [8] (::var"#5#8")() at ./task.jl:356
wait at ./task.jl:267 [inlined]
macro expansion at /home/yakir/.julia/dev/SimpleFanControl/src/simpler.jl:84 [inlined]
(::var"#3#6")() at ./task.jl:356

```

You can see my code [here](https://github.com/yakir12/SimpleFanControl.jl/blob/main/src/simpler.jl), but my issue might have to do with my misunderstanding of how serial ports work:

1. do I need to `flush` the port before every read/write?
2. Do I need to use locks to avoid simultaneously reading/writing from/into the port?
3. What happens if the device connected to the port (in my case an Arduino) sends messages faster than the computer retrieves them?

Appreciate any insight you might have!

---

<div class="post-metadata">

**Author:** ![contradict](https://avatars.discourse-cdn.com/v4/letter/c/ac91a4/32.png) [@contradict](https://discourse.julialang.org/u/contradict)\
**Post date:** [October 26, 2020, 5:53pm UTC](https://discourse.julialang.org/t/refvalue-errors-with-libserialport/49049/2 "2020-10-26T17:53:54Z")

</div>

I think the stack trace here is from pressing `Ctrl-C` to stop the process. I suspect it is hanging because `COBS` is not self-synchronizing, if the `flush` happens to discard the leading length byte, the next byte in the sequence becomes the length and things go off the rails.

There is definitely no need to flush the write buffer, so maybe try only flushing the read buffer by calling `sp_flush(a.sp, SP_BUF_INPUT)` in `sample!`and removing the call to `flush` on the write side.

---

<div class="post-metadata">

**Author:** ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)\
**Post date:** [October 26, 2020, 6:07pm UTC](https://discourse.julialang.org/t/refvalue-errors-with-libserialport/49049/3 "2020-10-26T18:07:53Z")

</div>

Thank you for taking such a in-depth look!  
Seems like it’s better, but I can still get some strange behavior. After reloading the page (again, this might have to do with how JSServe acts and my specific application) it stalls, and when I look into the async `reading` task I get:

```julia
 julia> reading
Task (failed) @0x00007f7f69965fc0
TaskFailedException:
AssertionError: isempty(session.message_queue)
Stacktrace:
 [1] send(::JSServe.Session, ::Dict{Symbol,Any}) at /home/yakir/.julia/packages/JSServe/9Z6uA/src/session.jl:83
 [2] #send#28 at /home/yakir/.julia/packages/JSServe/9Z6uA/src/session.jl:76 [inlined]
 [3] (::JSServe.JSUpdateObservable)(::Array{Any,1}) at /home/yakir/.julia/packages/JSServe/9Z6uA/src/observables.jl:14
 [4] #invokelatest#1 at ./essentials.jl:710 [inlined]
 [5] invokelatest at ./essentials.jl:709 [inlined]
 [6] setindex!(::Observable{Array{Any,1}}, ::Array{Any,1}; notify::Observables.var"#9#11") at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:207
 [7] setindex!(::Observable{Array{Any,1}}, ::Array{Any,1}) at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:201
 [8] (::WGLMakie.var"#7#8"{Observable{Array{Any,1}},Symbol})(::Tuple{typeof(setindex!),Tuple{Array{Point{2,Float32},1},Colon}}) at /home/yakir/.julia/packages/WGLMakie/QIWts/src/serialization.jl:190
 [9] #invokelatest#1 at ./essentials.jl:710 [inlined]
 [10] invokelatest at ./essentials.jl:709 [inlined]
 [11] setindex!(::Observable{Tuple{Function,Tuple}}, ::Tuple{typeof(setindex!),Tuple{Array{Point{2,Float32},1},Colon}}; notify::Observables.var"#9#11") at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:207
 [12] setindex!(::Observable{Tuple{Function,Tuple}}, ::Tuple{typeof(setindex!),Tuple{Array{Point{2,Float32},1},Colon}}) at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:201
 [13] setindex!(::ShaderAbstractions.ArrayUpdater{Array{Point{2,Float32},1}}, ::Array{Point{2,Float32},1}, ::Function) at /home/yakir/.julia/packages/ShaderAbstractions/vrRjy/src/types.jl:46
 [14] setindex! at /home/yakir/.julia/packages/ShaderAbstractions/vrRjy/src/types.jl:59 [inlined]
 [15] (::ShaderAbstractions.var"#9#10"{ShaderAbstractions.Buffer{Point{2,Float32},Array{Point{2,Float32},1}}})(::Array{Point{2,Float32},1}) at /home/yakir/.julia/packages/ShaderAbstractions/vrRjy/src/types.jl:146
 [16] #invokelatest#1 at ./essentials.jl:710 [inlined]
 [17] invokelatest at ./essentials.jl:709 [inlined]
 [18] setindex!(::Observable{Array{Point{2,Float32},1}}, ::Array{Point{2,Float32},1}; notify::Observables.var"#9#11") at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:207
 [19] setindex! at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:201 [inlined]
 [20] MapUpdater at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:326 [inlined]
 [21] (::Observables.OnUpdate{Observables.MapUpdater{typeof(first),Array{Point{2,Float32},1}},Tuple{Observable{Tuple{Array{Point{2,Float32},1},Array{Point{2,Float32},1}}}}})(::Tuple{Array{Point{2,Float32},1},Array{Point{2,Float32},1}}) at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:293
 [22] setindex!(::Observable{Tuple{Array{Point{2,Float32},1},Array{Point{2,Float32},1}}}, ::Tuple{Array{Point{2,Float32},1},Array{Point{2,Float32},1}}; notify::Observables.var"#9#11") at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:205
 [23] setindex! at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:201 [inlined]
 [24] MapUpdater at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:326 [inlined]
 [25] (::Observables.OnUpdate{Observables.MapUpdater{WGLMakie.var"#73#80"{Observable{StepRange{Int64,Int64}},Observable{StepRange{Int64,Int64}}},Tuple{Array{Point{2,Float32},1},Array{Point{2,Float32},1}}},Tuple{Observable{Base.ReinterpretArray{Point{2,Float32},1,Tuple{Point{2,Float32},Point{2,Float32}},GeometryBasics.TupleView{Tuple{Point{2,Float32},Point{2,Float32}},2,1,CircularBuffer{Point{2,Float32}}}}}}})(::Base.ReinterpretArray{Point{2,Float32},1,Tuple{Point{2,Float32},Point{2,Float32}},GeometryBasics.TupleView{Tuple{Point{2,Float32},Point{2,Float32}},2,1,CircularBuffer{Point{2,Float32}}}}) at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:293
 [26] setindex!(::Observable{Base.ReinterpretArray{Point{2,Float32},1,Tuple{Point{2,Float32},Point{2,Float32}},GeometryBasics.TupleView{Tuple{Point{2,Float32},Point{2,Float32}},2,1,CircularBuffer{Point{2,Float32}}}}}, ::Base.ReinterpretArray{Point{2,Float32},1,Tuple{Point{2,Float32},Point{2,Float32}},GeometryBasics.TupleView{Tuple{Point{2,Float32},Point{2,Float32}},2,1,CircularBuffer{Point{2,Float32}}}}; notify::Observables.var"#9#11") at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:205
 [27] setindex! at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:201 [inlined]
 [28] (::Observables.MapUpdater{WGLMakie.var"#70#77"{Combined{AbstractPlotting.lines,Tuple{CircularBuffer{Point{2,Float32}}}}},Base.ReinterpretArray{Point{2,Float32},1,Tuple{Point{2,Float32},Point{2,Float32}},GeometryBasics.TupleView{Tuple{Point{2,Float32},Point{2,Float32}},2,1,CircularBuffer{Point{2,Float32}}}}})(::CircularBuffer{Point{2,Float32}}) at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:326
 [29] (::Observables.OnUpdate{Observables.MapUpdater{WGLMakie.var"#70#77"{Combined{AbstractPlotting.lines,Tuple{CircularBuffer{Point{2,Float32}}}}},Base.ReinterpretArray{Point{2,Float32},1,Tuple{Point{2,Float32},Point{2,Float32}},GeometryBasics.TupleView{Tuple{Point{2,Float32},Point{2,Float32}},2,1,CircularBuffer{Point{2,Float32}}}}},Tuple{Observable{CircularBuffer{Point{2,Float32}}}}})(::CircularBuffer{Point{2,Float32}}) at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:293
 [30] setindex!(::Observable{CircularBuffer{Point{2,Float32}}}, ::CircularBuffer{Point{2,Float32}}; notify::Observables.var"#9#11") at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:205
 [31] setindex! at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:201 [inlined]
 [32] MapUpdater at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:326 [inlined]
 [33] (::Observables.OnUpdate{Observables.MapUpdater{AbstractPlotting.var"#183#185"{Int64},CircularBuffer{Point{2,Float32}}},Tuple{Observable{Tuple{CircularBuffer{Point{2,Float32}}}}}})(::Tuple{CircularBuffer{Point{2,Float32}}}) at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:293
 [34] setindex!(::Observable{Tuple{CircularBuffer{Point{2,Float32}}}}, ::Tuple{CircularBuffer{Point{2,Float32}}}; notify::Observables.var"#9#11") at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:205
 [35] setindex!(::Observable{Tuple{CircularBuffer{Point{2,Float32}}}}, ::Tuple{CircularBuffer{Point{2,Float32}}}) at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:201
 [36] (::AbstractPlotting.var"#201#203"{DataType,Observable{Tuple{CircularBuffer{Point{2,Float32}}}}})(::Tuple{}, ::Tuple{CircularBuffer{Point{2,Float32}}}) at /home/yakir/.julia/packages/AbstractPlotting/JCbJs/src/interfaces.jl:626
 [37] (::Observables.OnUpdate{AbstractPlotting.var"#201#203"{DataType,Observable{Tuple{CircularBuffer{Point{2,Float32}}}}},Tuple{Observable{Tuple{}},Observable{Tuple{CircularBuffer{Point{2,Float32}}}}}})(::Tuple{CircularBuffer{Point{2,Float32}}}) at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:293
 [38] setindex!(::Observable{Tuple{CircularBuffer{Point{2,Float32}}}}, ::Tuple{CircularBuffer{Point{2,Float32}}}; notify::Observables.var"#9#11") at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:205
 [39] setindex! at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:201 [inlined]
 [40] MapUpdater at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:326 [inlined]
 [41] (::Observables.OnUpdate{Observables.MapUpdater{typeof(tuple),Tuple{CircularBuffer{Point{2,Float32}}}},Tuple{Observable{CircularBuffer{Point{2,Float32}}}}})(::CircularBuffer{Point{2,Float32}}) at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:293
 [42] setindex!(::Observable{CircularBuffer{Point{2,Float32}}}, ::CircularBuffer{Point{2,Float32}}; notify::Observables.var"#9#11") at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:205
 [43] setindex! at /home/yakir/.julia/packages/Observables/A7I8T/src/Observables.jl:201 [inlined]
 [44] sample!(::Arduino) at /home/yakir/.julia/dev/SimpleFanControl/src/simpler.jl:72
 [45] (::var"#5#8")() at ./task.jl:356
wait at ./task.jl:267 [inlined]
macro expansion at /home/yakir/.julia/dev/SimpleFanControl/src/simpler.jl:84 [inlined]
(::var"#3#6")() at ./task.jl:356

```

> [@contradict](#):
>
> I suspect it is hanging because `COBS` is not self-synchronizing

`COBS.jl` is mine, is there anything specific I can do to remidy that, I’d love to improve it if possible!

---

<div class="post-metadata">

**Author:** ![contradict](https://avatars.discourse-cdn.com/v4/letter/c/ac91a4/32.png) [@contradict](https://discourse.julialang.org/u/contradict)\
**Post date:** [October 26, 2020, 7:06pm UTC](https://discourse.julialang.org/t/refvalue-errors-with-libserialport/49049/4 "2020-10-26T19:06:23Z")

</div>

That one is less clear to me, but I suspect the reload invalidates whatever channel read was using to communicate back to the web page. You probably need to re-start reading when the page reloads.

By self-synchronizing I mean that each message sent over the serial port has an unambiguous start and end. This means that if you start reading part way through a message, you can discard bytes until you get to the next full packet. Common techniques are start end bytes (with escaping to include those bytes like [SLIP](https://en.wikipedia.org/wiki/Serial_Line_Internet_Protocol) or [HDLC](https://en.wikipedia.org/wiki/High-Level_Data_Link_Control#Asynchronous_framing)), using a format that re-encodes everything using a restricted byte range (sending text and parsing it on the other end), or using checksums (still can use framing bytes, but only packets that also pass a checksum calculation are valid). Encoding the packet length is always tricky, some protocols avoid this entirely by always sending a fixed length packet or by separately framing a fixed-length header encoding the data length. Other fun things to look at:

[Modbus](https://en.wikipedia.org/wiki/Modbus)

[MAVLink](https://en.wikipedia.org/wiki/MAVLink)

A good search term is “framing protocol” or “serial framing”.

Implementing your own serial framing protocol is a fun project, but test it well, there are a tremendous number of corner cases to handle in a working protocol.

---

<div class="post-metadata">

**Author:** ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)\
**Post date:** [October 26, 2020, 7:12pm UTC](https://discourse.julialang.org/t/refvalue-errors-with-libserialport/49049/5 "2020-10-26T19:12:53Z")

</div>

Right now it would be great to have one package that was very good at solving the framing problem. I encountered this problem a while ago, which led to [COBS.jl](https://github.com/yakir12/COBS.jl) (see [this thread](https://discourse.julialang.org/t/ann-consistent-overhead-byte-stuffing-cobs-jl) for instance). But I did that because there was no alternative back then, do you know if there is one now? I’d welcome any PR you might have to `COBS.jl`.

---

<div class="post-metadata">

**Author:** ![contradict](https://avatars.discourse-cdn.com/v4/letter/c/ac91a4/32.png) [@contradict](https://discourse.julialang.org/u/contradict)\
**Post date:** [October 26, 2020, 9:54pm UTC](https://discourse.julialang.org/t/refvalue-errors-with-libserialport/49049/6 "2020-10-26T21:54:02Z")

</div>

I’ll take a closer look if I get a chance and see if I can figure out exactly what is going on, I think I misread your code the first time through. It does look like a zero byte should unambiguously end a packet, so I’m not sure what is going on.

---

<div class="post-metadata">

**Author:** ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)\
**Post date:** [October 27, 2020, 7:26am UTC](https://discourse.julialang.org/t/refvalue-errors-with-libserialport/49049/7 "2020-10-27T07:26:22Z")

</div>

I’m gonna try to switch to a model where the computer asks the Arduino for a message and then and only then does the Arduino send one. This way the communication will be on the computer’s terms instead of the Arduino continuously spamming the channel and the computer trying to catch up. I’ll push my attempt and report back here…

---

<div class="post-metadata">

**Author:** ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)\
**Post date:** [October 27, 2020, 11:39am UTC](https://discourse.julialang.org/t/refvalue-errors-with-libserialport/49049/8 "2020-10-27T11:39:50Z")

</div>

OK, that issue got resolved thanks to the magical Simon Danisch. The problem was that I was adding more and more listeners to an observable by reloading the webpage. Bu clearing them off first I managed to remove that problem altogether. I did change models to the arduino sending messages only when asked to, that might have helped. In any case, it’s working now, which is awesome!
