I am sending data via Serial to an Arduino. I want to build error checking, so I don't want to send the next command until the previous has "checked out".
In the pseudo code below, I want to prevent the next command .pop
until the process
has "released" the next command. Otherwise I want to retry the previous command.
Ideally, the lock would happen just as send starts.
class Arduino
@threads = []
def initialize
# Connect to arduino serial
@serial
start_queues
end
def start_queues
#read from serial
@threads << Thread.new do
while line = @serial.readline
process(line)
end
end
#pop from queue to send to Arduino
@threads << Thread.new do
loop do
send(Queue.send_queue.pop)
# Wait here until previous command completes properly
end
end
end
def process(data)
# Check cmd
# If success, 'send' next command
# If error, requeue & 'send'
end
def send(data)
@serial.write(data)
end
end
Using Mutexe
s and ConditionalVariable
s I was able to lock the "sending" thread.
For anyone looking at multithreading, hope this helps:
class Arduino
def initialize
@threads = []
@work_queue = Queue.new
@mutex = Mutex.new
@cmd_lock = ConditionVariable.new
@serial = Queue.new
# Connect to arduino serial
start_queues
end
def start_queues
#read from serial
@threads << Thread.new do
loop do
process(@serial.pop)
end
end
#pop from queue to send to Arduino
@threads << Thread.new do
loop do
@mutex.synchronize do
send(@work_queue.pop)
@cmd_lock.wait(@mutex)
end
end
end
end
def process(data)
puts data
# Check cmd
if data == "example1"
@cmd_lock.signal
end
end
def send(data)
@serial << data
end
def go
puts "GO"
@work_queue << "example1"
@work_queue << "example2"
@work_queue << "example3"
@threads.each(&:join)
end
end
Arduino.new.go