Forum: PC-Programmierung ruby-serialport unter Ubuntu


von Uhu U. (uhu)


Lesenswert?

Ich möchte unter Ubuntu Daten mit ruby über /dev/ttyUSB0 austauschen.

Nach viel Gemurkse und einer Quelltext-Änderung in serialport.c habe ich 
es endlich geschafft, mit Serialport.new den Port zu öffnen.

Nun ist schon die nächste Klippe aufgetaucht:
1
require "serialport.so"
2
3
sp = SerialPort.new(0, 115200)          # Öffnet /dev/ttyUSB0
4
5
sp.putc('#')

Schmiert bei sp.putc mit "Uncaught exception: not opened for writing" 
ab.

/dev/ttyUSB0 hat rw-Permissions für alle und kann mit GTK-Term ohne 
Probleme geschrieben und gelesen werden.

Hat jemand eine Idee, was da faul ist?

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Also hier:
http://ruby-serialport.rubyforge.org/
Wir zumindest der Name des Port benötigt als erster Parameter, was macht 
den die 0 da? Wenn ich die Doku verstehe mappt die nämlich defaultmäßig 
nach /dev/ttyS0 und nicht nach /dev/ttyUSB0

von Uhu U. (uhu)


Lesenswert?

Laut Beschreibung kann der erste Parameter eine Device-Nummer (0 für 
/dev/ttyS0, oder COM1:) sein oder ein String, wie z.B. "/dev/ttyUSB0" 
sein. Der Code unterscheidet intern an dieser Stelle auch zwischen einem 
Int-Wert und einem String. Nur funktioniert das mit dem String aus mir 
im Moment undurchsichtigen Gründen nicht - er will dort keinen String 
sehen.

Umschifft habe ich das, indem ich im Posix-Implementierungsmodul die 
Devicenamen von /dev/ttyS* nach /dev/ttyUSB* geändert habe. Damit 
funktioniert wenigstens das Serialport.new(0, 115200).

So viel zur Vorgeschichte. Jetzt darfst du dich zum eigentlichen Problem 
äußern ;-)

Gleich noch eine Randfrage:
Gibts für gcc irgendwas, womit man einen Debugger-Breakpoint fest 
eincodieren kann? Unter der verfluchten Windows 9x-Linie konnte man das 
sehr bequem mit asm int 3 machen - zumindest mit den 
Nicht-GNU-Compilern.

von Uhu U. (uhu)


Lesenswert?

So siehts aus, wenn man versucht den SerialPort mit String im irb zu 
öffnen:
1
$ irb
2
irb(main):001:0> require 'rubygems'
3
=> true
4
irb(main):002:0> require 'serialport.so'
5
=> true
6
irb(main):003:0> sp=SerialPort.new("/dev/ttyUSB0", 9600)
7
TypeError: can't convert String into Integer
8
  from (irb):3:in `initialize'
9
  from (irb):3:in `new'
10
  from (irb):3
11
irb(main):004:0>

von Klaus W. (mfgkw)


Lesenswert?

Uhu Uhuhu schrieb:
> Gleich noch eine Randfrage:
> Gibts für gcc irgendwas, womit man einen Debugger-Breakpoint fest
> eincodieren kann? Unter der verfluchten Windows 9x-Linie konnte man das
> sehr bequem mit asm int 3 machen

Auch unter neueren Windows-Versionen geht es z.B. mit CrtDbgBreak() mit 
VC++.

von Uhu U. (uhu)


Lesenswert?

Und mit gcc unter Linux?

von Klaus W. (mfgkw)


Lesenswert?

Wenn ich das aus dem Stegreif wüsste, hätte ich es dir verraten...

von Uhu U. (uhu)


Lesenswert?

Klaus Wachtler schrieb:
> Auch unter neueren Windows-Versionen geht es z.B. mit CrtDbgBreak() mit
> VC++.

Demgegenüber hatte der int 3 - Trick den Vorteil, daß der Debugger auch 
wirklich in meinem Quelltext auf dem int 3 stand. Mit CrtDbgBreak() 
findet man sich irgendwo ein paar Etagen tiefer und muß sich dort erst 
wieder rauswurschteln.

von Uhu U. (uhu)


Lesenswert?

Soviel ich bisher mit gdb herausgefunden habe, wird aus irgenwelchen 
komischen Gründen create nicht aufgerufen, der Port ist also nicht 
offen.

Irgendwo ist da der Oberwurm drin...

von Klaus W. (mfgkw)


Lesenswert?

So etwas herauszufinden geht mit strace einfacher und zuverlässiger als 
mit dem gdb.
Z.B. Debian:
apt-get install strace
strace irgendein Kommando....


Abgesehen davon, daß es nicht create heißt, sondern creat, und 
vielleicht auch das nicht aufgerufen wird, sondern open (aus OS-Sicht 
bzw. in der C-Lib; von ruby rede ich nicht mangels jeglichen Wissens).

von Uhu U. (uhu)


Lesenswert?

Klaus Wachtler schrieb:
> Abgesehen davon, daß es nicht create heißt, sondern creat, und
> vielleicht auch das nicht aufgerufen wird, sondern open (aus OS-Sicht
> bzw. in der C-Lib; von ruby rede ich nicht mangels jeglichen Wissens).

Der Quelltext gibt das nicht her. Dort heißt die betreffende Routine 
sp_create, ein Berakpoint darauf triggert nicht und ein Kommentar 
darüber sagt:
1
/*
2
 * :nodoc: This method is private and will be called by SerialPort#new or SerialPort#open.
3
 */

Die Modul-Initialisierung Init_serialport kann ich per GDB fangen. Ich 
werde mal versuchen, nach der Initialisierung weiter zu debuggen...

strace ergibt zwar 1,3 MB Daten, aber auch keine andere Erkenntnis. 
/dev/tty* kommt darin nicht vor.

von Daniel -. (root)


Lesenswert?

geht es dir um eine Lösung in ruby oder suchst du
eine pragmatische Lösung für ein Problem?

ich habe auf die schnelle immer Python genommen
http://pyserial.sourceforge.net/pyserial_api.html

ist schon etwas her, aber ich meine das die Lösung
sogar zwischen win <-> lin portabel war.

btw, wenn ich mir gerade code Stücke anschaue, die
google ausspuckt, scheinen alle Möglichkeiten
im Konstruktor zu gehen
http://www.python-forum.org/pythonforum/viewtopic.php?f=3&t=27500

http://stackoverflow.com/questions/1093598/pyserial-how-to-read-last-line-sent-from-serial-device

http://stackoverflow.com/questions/676172/full-examples-of-using-pyserial-package

.. eine saubere ruby Lösung würde mich übrigens auch interessieren
Hoffentlich bekommt die ruby community eine reiche und durchdacht
strukturierte Bib auf die Beine.

von Uhu U. (uhu)


Lesenswert?

Ich bin der Ursache des Problems ein Stückchen näher gekommen: 
SerialPort.new ruft nicht SerialPort#create, (die ist in ruby definiert) 
sondern gleich IO#create.

Letztere akzeptiert nur eine File-Nummer als ersten Parameter.

Im Moment weiß ich leider noch nicht, wie das passieren kann. Er scheint 
aus irgend welchen komischen Gründen serialport.rb zu ignorieren.

Vorher muß ich aber erst mal mein Ruby-System wieder flott kriegen. Ich 
hatte mir den Quellbaum von Github geholt, 1.8.7 ausgecheckt und 
installiert, nachdem ich das Ruby von Ubuntu im Paketmanager 
deinstalliert hatte.

Seither scheitert Ruby schon an require 'rubygems' und require 'tk'. 
Weiß der Henker, was da verbogen ist.

von Uhu U. (uhu)


Lesenswert?

So, ich habs unter Ubuntu zum Laufen bekommen, und zwar so:

- SerialPort gemaket, wie es in der README beschrieben ist
- require '<vollständiger pfad zu serialport.so (das so kann man
  weglassen)
- Die Definition von class SerialPort aus lib/serialport.rb in meinen
  Quelltext kopieren.

Es ist mir bisher noch nicht gelungen, Ruby dazu zu bewegen, den 
.rb-Text automatisch per require, oder include in mein Programm 
hinein zu bekommen.

Irgend was muß da an der Extension faul sein. Ich habe noch nicht 
versucht, das Teil unter Windows zu installieren - vielleicht gehts ja 
dort...

von Micha C. (Gast)


Lesenswert?

Hallo,

ich setze ruby-serialport schon eine Zeitlang unter Debian und Ubuntu 
ein
und hatte bisher keine großen Probleme.

Anbei ein Schnipsel von der Initialisierung der "seriellen" 
Schnittstelle.

===== SCHNIPP =====
require 'serialport'
require 'thread'
require 'io/nonblock'

@device = "/dev/ttyUSB0"
@baudrate = 9600

@port = SerialPort.new( @device, @baudrate, 8, 1, SerialPort::NONE)

@port.nonblock = true
@port.sync = true

@port.flow_control = SerialPort::SOFT
===== SCHNAPP =====

Einzig der Wechsel von Ruby1.8 auf Ruby1.9 war nicht ganz 
unproblematisch, dort hat sich die Schnittstelle ein wenig geändert.


Gruss

    Micha

von Uhu U. (uhu)


Lesenswert?

Wo und wie hast du das Teil gezogen?

Das was ich mir von github heruntergeladen habe, scheint im Quelltext 
schon für 1.9 modifiziert zu sein. Ich benutze es aber mit 1.8.7

von Micha C. (Gast)


Lesenswert?

Hallo,

> Wo und wie hast du das Teil gezogen?
>
> Das was ich mir von github heruntergeladen habe, scheint im Quelltext
> schon für 1.9 modifiziert zu sein. Ich benutze es aber mit 1.8.7
für Ruby 1.8 habe ich einfach das angebotene Paket direkt von 
Debian/Ubuntu installiert. Für Ruby 1.9 habe ich das Paket aus den 
Debian/Ubuntu-Quellen selbst erstellt. Beide Pakete basieren noch auf 
der Version 0.7.0 von ruby-serialport.

Bei Ruby 1.8.7 sollte eigentlich das von Debian/Ubuntu angebotene Paket 
tun.


Gruss

    Micha

von Uhu U. (uhu)


Lesenswert?

Das, was ich hier habe, hat die Version 1.0.4

Nachtrag:
Na super, bei Ubuntu heißt das Paket libserialport-ruby. Ich hab immer 
brav nach ruby-serialport gesucht...

Danke für den Hinweis.

2. Nachtrag:
Mit libserialport-ruby bekomme ich wieder den alten Fehler, daß er als 
ersten Parameter keinen String akzeptieren will - warum er die 
class-Definition nicht findet, wenn ich sie nicht im eigenen Quelltext 
habe, bleibt rätselhaft.

von Uhu U. (uhu)


Lesenswert?

Mittlerweile habe ich serialport.rb in das Verzeichnis kopiert, in dem 
nach der Installation des Ubuntu-Paketes serialport.so liegt und in 
meinem Quelltext das require-Statement nach

     require 'serialport'

geändert. Nun gehts, denn das require 'serialport.so' steht in der .rb 
und lädt so die Extension. Sieht also erst mal so aus, als sei da im 
Installationspaket irgendwas nicht so, wie es sein sollte.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.