2010-11-06 10 views
7

Estoy tratando de enviar un número entero sobre el puerto serie a mi Ardunio. El chip mostrará el número en binario en los LED. Sin embargo, tengo muchos problemas para tratar de enviar los datos como un byte sobre el puerto serie, en lo que puedo depurar, el siguiente código lo envía como valores de ASC char.Escribir byte en Arduino desde Ruby sobre la serie

¿Alguien puede señalarme en la dirección correcta o detectar el error? Realmente lo apreciaría. He estado tirando de mi cabello sobre esto durante mucho tiempo.

Rubí

require 'rubygems' 
require 'serialport' # use Kernel::require on windows, works better. 

#params for serial port 
port_str = "/dev/tty.usbserial-A700dZt3" #may be different for you 
baud_rate = 9600 
data_bits = 8 
stop_bits = 1 
parity = SerialPort::NONE 

sp = SerialPort.new(port_str, baud_rate, data_bits, stop_bits, parity) 

i = 15 

#just write forever 
while true do 
    sp.write(i.to_s(2)) 
    sleep 10 
end 

Arduino

int ledPin = 10; 
int ledPin1 = 11; 
int ledPin2 = 12; 
int ledPin3 = 13; 

byte incomingByte; // for incoming serial data 

void setup() { 
    pinMode(ledPin, OUTPUT); // initialize the LED pin as an output: 
    pinMode(ledPin1, OUTPUT); // initialize the LED pin as an output: 
    pinMode(ledPin2, OUTPUT); // initialize the LED pin as an output: 
    pinMode(ledPin3, OUTPUT); // initialize the LED pin as an output: 
    Serial.begin(9600); 
    Serial.println("I am online"); 
} 

void loop() { 
// send data only when you receive data: 
if (Serial.available() > 0) { 
    incomingByte = Serial.read(); 
      Serial.println(incomingByte, DEC); 

    int value = (incomingByte, DEC) % 16; 
    digitalWrite(ledPin, (value >> 0) % 2); 
    digitalWrite(ledPin1, (value >> 1) % 2); 
    digitalWrite(ledPin2, (value >> 2) % 2); 
    digitalWrite(ledPin3, (value >> 3) % 2); // MSB 

} 

} 
+0

¿Ha intentado usar un programa de terminal en lugar de Ruby? ¿Es esta tu primera configuración o ya tienes algo funcionando? –

Respuesta

5

Supongo que está intentando escribir el valor 15 para encender todos los LED a la vez.Sin embargo, 15.to_s(2) es "1111". El valor ASCII del carácter "1" es 49, por lo que en lugar de escribir 15 una vez que está escribiendo 49 cuatro veces en rápida sucesión.

El comando de escritura que está buscando es por lo tanto probablemente sp.putc(i). Esto escribe solo un carácter con el valor binario dado (= legible por máquina para Arduino) en lugar de una representación de cadena ASCII del valor expresado en binario (= legible para usted).

Así manteniendo todo lo demás igual, vuelva a colocar el bucle while en su código Ruby con:

loop do 
    sp.putc(i) 
    puts 'Wrote: %d = %bb' % [ i, i ] 
    i = (i == 15) ? 0 : (i + 1) 
    sleep(10) 
end 

Si desea leer las respuestas de Arduino, se puede utilizar, por ejemplo, sp.gets para obtener una línea de texto, p. intente colocar puts 'Arduino replied: ' + sp.gets en el bucle antes de sleep (y un puts sp.gets antes del bucle para leer el mensaje "Estoy en línea" enviado cuando se establece por primera vez la conexión).

Editar: que sólo vio otro problema en su código, en el lado de Arduino: value = (incomingByte, DEC) % 16; siempre resulta en el valor 10 porque (incomingByte, DEC) tiene el valor DEC (que es 10). Debería usar value = incomingByte % 16; en su lugar. O elimine el value en conjunto y modifique incomingByte en sí mismo, p. incomingByte %= 16;.

+0

Como una optimización menor en el microcontrolador, con las asignaciones de pines 10-13 también podría reemplazar las líneas 'digitalWrite' con (uno) 'PORTB = ((incomingByte & 0x0F) << 2) | (PORTB y 0xC3); '. – Arkku

+0

Estoy respaldando esta respuesta, tiene la mayor parte de lo que iba a decir. También, sin embargo, las líneas 'digitalWrite (ledPin, (valor >> 0)% 2);' podrían ser un problema. No sé si es seguro asumir HGIH y el mapa BAJO a 1 y 0. Y generalmente el pin 13 es un pin dudoso para usar, porque tiene una resistencia incorporada. –

+0

Sí, el mapa "ALTO" y "BAJO" a 0 y 1. =) Lo que no es seguro asumir es que los bits en 'PORTB' se asignan a pines físicos específicos, pero esto es solo un problema si se mueve a un μC diferente en En ese caso, las conexiones físicas también podrían moverse. (Si los pines correspondientes en 'PORTB' están disponibles.) – Arkku

1

que he tenido este trabajo código Ruby antes

while true do 
    printf("%c", sp.getc) 
end 

en lugar de utilizar sp.write(i.to_s). Parece que lo está convirtiendo explícitamente en una cadena, que puede ser la causa de sus problemas.

me encontré con el blog original que utilicé: http://www.arduino.cc/playground/Interfacing/Ruby

1

Ha pasado tanto tiempo desde que hice nada con puertos serie que no puedo ayudar, pero sí veo una cosa.

>> 15.to_s #=> "15" 

y

>> 15.to_s(2) #=> "1111" 

Creo que si se desea que el valor binario que se enviará querrá "\xf" o "\u000F".


cambiar su código de:

while true do 
    sp.write(i.to_s(2)) # <-- this sends a multi-character ASCII representation of the "i" value, NOT the binary. 
    sleep 10 
end 

a:

while true do 
    sp.write(i.chr) # <-- this sends a single byte binary representation of the "i" value, NOT the ASCII. 
    sleep 10 
end 

Para mostrar la diferencia, aquí está la longitud de las cuerdas que se emite:

>> 15.to_s(2).size #=> 4 
>> 15.chr.size #=> 1 

Y los valores decimales de los bytes comp Aumento de las cadenas:

>> 15.to_s(2).bytes.to_a #=> [49, 49, 49, 49] 
>> 15.chr.bytes.to_a #=> [15] 
+0

Gracias por la sugerencia que probé con sp.write 9.to_s (2) pero todavía no parece querer funcionar. –

+1

Bueno, '9.to_s (2)' no es una representación binaria de 9. Es una representación de cadena. Tendría que usar algo como '" \ x9 "' o '" \ x0009 "' o '[9] .pack ('c')'. Hay una diferencia entre parecer visualmente como la representación binaria y * ser * el binario. –

1

Sus problemas pueden deberse al almacenamiento en búfer. Para deshabilitar el almacenamiento en búfer, se puede hacer una de las siguientes:

  • Set sp to unbuffered después de crearlo (antes de la escritura): sp.sync = true
  • llamada flush después de la write
  • Uso del sin búfer syswrite en lugar de escribir
+0

O configure 'sp.sync = true' inmediatamente después de abrir el puerto. –

+0

Gracias, Greg. Editado –

+0

Gracias por la sugerencia, mucha gente ha agregado sp.sync = verdadero, pero parece que todavía no funciona correctamente –

Cuestiones relacionadas