Write byte to Arduino from Ruby over serial - ruby

I'm trying to send an integer over the serial port to my Ardunio. The chip is then going to display the number in binary on the LED's. However I'm having lots of trouble trying to send the data as a byte over the serial port, as far as I can debug the following code sends it as the ASC char values.
Can anyone point me in the right direction or spot the mistake? I'd really appreciate it. I've been pulling my hair out over this for a long time.
Ruby
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
}
}

I'm guessing you are trying to write the value 15 in order to light all the LEDs at once. However, 15.to_s(2) is "1111". The ASCII value of the character '1' is 49, so instead of writing 15 once you are writing 49 four times in rapid succession.
The write command you are looking for is therefore probably sp.putc(i). This writes only one character with the given binary value (= machine-readable for Arduino) instead of an ASCII string representation of the value expressed in binary (= human-readable for you).
So keeping everything else the same, replace the while loop in your Ruby code with:
loop do
sp.putc(i)
puts 'Wrote: %d = %bb' % [ i, i ]
i = (i == 15) ? 0 : (i + 1)
sleep(10)
end
If you wish to read the responses from Arduino, you can use e.g. sp.gets to get one line of text, e.g. try placing puts 'Arduino replied: ' + sp.gets in the loop before sleep (and one puts sp.gets before the loop to read the "I am online" sent when the connection is first established).
Edit: I just spotted another problem in your code, on the Arduino side: value = (incomingByte, DEC) % 16; always results in the value 10 because (incomingByte, DEC) has the value DEC (which is 10). You should use value = incomingByte % 16; instead. Or do away with value altogether and modify incomingByte itself, e.g. incomingByte %= 16;.

Your problems may be caused by buffering. To disable buffering, you can do one of the following:
Set sp to unbuffered after creating it (before writing): sp.sync = true
Call flush after the write
Use the unbuffered syswrite instead of write

It's been so long since I did anything with serial ports that I can't help there, but I do see one thing.
>> 15.to_s #=> "15"
and
>> 15.to_s(2) #=> "1111"
I think if you want the binary value to be sent you'll want "\xf" or "\u000F".
Change your code from:
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
to:
while true do
sp.write(i.chr) # <-- this sends a single byte binary representation of the "i" value, NOT the ASCII.
sleep 10
end
To show the difference, here's the length of the strings being output:
>> 15.to_s(2).size #=> 4
>> 15.chr.size #=> 1
And the decimal values of the bytes comprising the strings:
>> 15.to_s(2).bytes.to_a #=> [49, 49, 49, 49]
>> 15.chr.bytes.to_a #=> [15]

I've had this Ruby code work before
while true do
printf("%c", sp.getc)
end
rather than using sp.write(i.to_s). It looks like you are explicitly converting it to a string, which may be the cause of your problems.
I found the original blog post I used:
http://www.arduino.cc/playground/Interfacing/Ruby

Related

keyboard emulator device behavior on ubuntu

I'm building a device driver of sorts that consumes data from a keyboard emulating device.
The device is a card swipe, so its behavior is as follows:
User walks up, swipes card
I get a string of characters (key codes, really, including modifier keys for capital letters)
I don't know how many characters I'm going to get
I don't know when I'm getting something
Since I don't know how many characters I'm going to get, blocking reads on the keyboard tty aren't useful - I'd end up blocking after the last character. What I'm doing is, in Ruby, using the IO module to perform async reads against the keyboard device, and using a timeout to determine that the end of data was reached. This works fine logically (even a user swiping his or her card fast will do so slower than the send rate between characters).
The issue is that sometimes, I lose data from the middle of the string. My hunch is that there's some sort of buffer overflow happening because I'm reading the data too slowly. Trying to confirm this, I inserted small waits in between each key process. Longer waits (20ms+) do exacerbate the problem. However, a wait of around 5ms actually makes it go away? The only explanation I can come up with is that the async read itself is expensive (because Ruby), and doing them without a rate limit is actually slower than doing them with a 5ms delay.
Does this sound rational? Are there other ideas on what this could be?
The ruby is actually JRuby 9000. The machine is Ubuntu LTS 16.
Edit: here's a snippet of the relevant code
private def read_swipe(buffer_size, card_reader_input, pause_between_reads, seconds_to_complete)
limit = Time.now + seconds_to_complete.seconds
swipe_data = ''
begin
start_time = Time.now
sleep pause_between_reads
batch = card_reader_input.read_nonblock(buffer_size)
swipe_data << batch
rescue IO::WaitReadable
IO.select([card_reader_input], nil, nil, 0.5)
retry unless limit < start_time
end while start_time < limit
swipe_data
end
where card_reader_input = File.new(event_handle, 'rb')
I am not sure about Ruby code but you can use linux sysfs to access the characters coming out of keyboard 'like' device, and if feasible you can call C code from ruby application. I had done this for barcode reader and following is the code:
static int init_barcode_com(char* bcr_portname)
{
int fd;
/* Open the file descriptor in non-blocking mode */
fd = open(bcr_portname, O_RDONLY | O_NOCTTY | O_NDELAY);
cout << "Barcode Reader FD: " << fd <<endl;
if (fd == -1)
{
cerr << "ERROR: Cannot open fd for barcode communication with error " << fd <<endl;
}
fcntl(fd, F_SETFL, 0);
/* Set up the control structure */
struct termios toptions;
/* Get currently set options for the tty */
tcgetattr(fd, &toptions);
/* Set custom options */
/* 9600 baud */
cfsetispeed(&toptions, B9600);
cfsetospeed(&toptions, B9600);
/* 8 bits, no parity, no stop bits */
toptions.c_cflag &= ~PARENB;
toptions.c_cflag &= ~CSTOPB;
toptions.c_cflag &= ~CSIZE;
toptions.c_cflag |= CS8;
/* no hardware flow control */
toptions.c_cflag &= ~CRTSCTS;
/* enable receiver, ignore status lines */
toptions.c_cflag |= CREAD | CLOCAL;
/* disable input/output flow control, disable restart chars */
toptions.c_iflag &= ~(IXON | IXOFF | IXANY);
/* disable canonical input, disable echo,
* disable visually erase chars,
* disable terminal-generated signals */
toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
/* disable output processing */
toptions.c_oflag &= ~OPOST;
/* wait for n (in our case its 1) characters to come in before read returns */
/* WARNING! THIS CAUSES THE read() TO BLOCK UNTIL ALL */
/* CHARACTERS HAVE COME IN! */
toptions.c_cc[VMIN] = 0;
/* no minimum time to wait before read returns */
toptions.c_cc[VTIME] = 100;
/* commit the options */
tcsetattr(fd, TCSANOW, &toptions);
/* Wait for the Barcode to reset */
usleep(10*1000);
return fd;
}
static int read_from_barcode_reader(int fd, char* bcr_buf)
{
int i = 0, nbytes = 0;
char buf[1];
/* Flush anything already in the serial buffer */
tcflush(fd, TCIFLUSH);
while (1) {
nbytes = read(fd, buf, 1); // read a char at a time
if (nbytes == -1) {
return -1; // Couldn't read
}
if (nbytes == 0) {
return 0;
}
if (buf[0] == '\n' || buf[0] == '\r') {
return 0;
}
bcr_buf[i] = buf[0];
i++;
}
return 0;
}
Now that you do not know how many characters your going to get you can use VMIN and VTIME combination to address your concern. This document details various possibilities with VMIN and VTIME.

Parsing float from i2c with ruby on raspberry pi

this is mostly a ruby question.
I'm stuck trying to parse some bytes from an i2c device to a float value on ruby.
Long story:
I'm trying to read a float value from an i2c device with raspberry pi and an AtTiny85 (the device). i'm able to read its value from console through i2ctools
Example:
i2cset -y 0 0x25 0x00; sleep 1; i2cget -y 0 0x25 0x00; i2cget -y 0 0x25 0x00; i2cget -y 0 0x25 0x00; i2cget -y 0 0x25 0x00
Gives me:
0x3e
0x00
0x80
0x92
that means 0.12549046, which is a value in volts that i'm able to check with my multimeter and is ok. (the order of the bytes is 0x3e008092)
Now i need to get this float value from a ruby script, I'm using the i2c gem.
A comment on this site suggest the following conversion method:
hex_string = '42880000'
float = [hex_string.to_i(16)].pack('L').unpack('F')[0]
# => 68.0
float = 66.2
hex_string = [float].pack('F').unpack('L')[0].to_s(16)
# => 42846666
But i haven't been able to get this string of hex values. This fraction of code:
require "i2c/i2c"
require "i2c/backends/i2c-dev"
#i2c = ::I2C.create("/dev/i2c-0")
sharp = 0x25
#i2c.write(sharp, 0)
sleep 1
puts #i2c.read(sharp, 4).inspect
Puts on screen
">\x00\x00P"
Where the characters '>' and 'P' are the ASCII values of the byte in that position, but then i cannot know where/how to split the string and clean it up to at least try the method showed above.
I could write a C program to read the value and printf it to console or something and run it from ruby, but i think that would be an awful solution.
Some ideas on how can this be done would be very helpful!
Greetings.
I came with something:
bytes = []
for i in (0..3) do
bytes << #i2c.read_byte(sharp).unpack('*C*')[0].to_s(16)
bytes[i] = "00" unless bytes[i] != "0"
end
bytes = bytes.join.to_s
float = [bytes.to_i(16)].pack('L').unpack('F')[0]
puts float.to_s
Not shure about unpack(' * C * ') though, but it works. If it's a better way to do it i'd be glad with another answer.
Greetings!
You probably just need to use unpack with a format of g, or possible e depending on the endianness.
#i2c.read(sharp, 4).unpack('g')[0]
The example you are referring to is taking a string of hex digits and first converting it to a binary string (that’s the [hex_string.to_i(16)].pack('L') part) before converting to an integer (the L directive is for 32 bit integers). The data you have is already a binary string, so you just need to convert it directly with the appropriate directive for unpack.
Have a read of the documentation for unpack and pack.

Low Power Mode on the TI MSP430

I am using the MSP430F2274 and trying to understand better the uses of Low Power mode.
In my program I am also using the SimplicTi API in order for two devices (one is the AP which is being connected by the other ,ED) to communicate.
AP - Access Point , which is also connected to a PC via the UART in order to recive a string from the user.
ED - End Device , simply connetes to the AP (with the SimplicTi protocol) and waits for messages form it.
I want to be sure I understand the low power mode uses , and to see how it "comes along" with the SimplicTi API.
The "flow" of the AP is as follows (after it is "linked" to the ED , see the code bellow):
#pragma vector = USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
// **A)** extract the "RXed" character (8 bits received from user) , use the while
// in order to be sure all the 8 bits are "desirialized" into a byte
while (!(IFG2 & UCA0RXIFG));
input_char = UCA0RXBUF; // input_char is global variable.
// **B)** if we received the "Enter" character , which indicates the
// end of the string
if(input_char == '\r' && input_count > 0)
{
TACCR0 = 10; // **F)**
TACTL = TASSEL_1 + MC_1; // ACLK, up mode
// **E)** Enter LPM3, interrupts enabled !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
__bis_SR_register(LPM3_bits + GIE);
}//end if Enter
// **C)** Any other char of the user's string when we
// have not got more than the maximum amount of bytes(chars)
else if (((FIRST_CHAR <= input_char && input_char <= LAST_CHAR) || ('a' <= input_char && input_char <= 'z')) && (input_count < INPUT_MAX_LENGTH))
{
input[input_count++] = input_char;
}
} //end of UART RX INTERRUPT
The TIMERA0 Interrupt Handler is the following code:
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A(void)
{
if (i == strlen(morse)) // **D)** morse is a global array of chars who holds the string that we wish to send
{
SMPL_Send(sLID[0], (uint8_t*)EOT, 1); // EOT is the last char to send
TACTL = MC_0; //disable TimerA0
}
else if (!letterSpace)
{
char ch = morse[i++];
SMPL_Send(sLID[0], (char*)ch, 1);
switch(ch)
{
case '.':
{
TACCR0 = INTERVAL * 3;
letterSpace = 1;
break;
}
case '-':
{
TACCR0 = INTERVAL * 3 * 3;
letterSpace = 1;
break;
}
} // switch
} // else if
} //end TIMERA0 interrupt handler
The thing is like that:
I use the TIMERA0 handler in order to send each byte after a different amount of type , whether the char was transformed into a "-" or a "."
To do so I set the timer accordingly to a different value ( 3 times larger for "-").
Finnaly when I am done transmitting the whole string (D) , I disable the timer.
NOTE : The following method is performed at the begining of the AP code in order to configure the UART:
void UARTinit()
{
P3SEL = 0x30; // P3.4 and P3.5 as the UART TX/RX pins: P3SEL |= BIT4 + BIT5;
UCA0CTL1 |= UCSSEL_2; // SMCLK
// pre scale 1MHz/9600 =~ 104.
UCA0BR0 = 104;
UCA0BR1 = 0;
// 8-bit character and Modulation UCBRSx = 1
UCTL0 |= CHAR;
UCA0MCTL = UCBRS0;
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
IE2 |= UCA0RXIE; // Enable UART INPUT interrupt
} // end of UARTinit
So my questions are:
1) Just to be sure, in A) where I am "polling" the Rx buffer of the UART , is it necceary or is it just good practise for "any case" , cause AFAIK the UART handler gets called once the UART module recived the whole BYTE (as I configured it)?
2) In the main program of the AP , the last instruction is the one that "puts" it into LPM0 with interrupts enables : __bis_SR_register(LPM0_bits + GIE);
When for LPM0:
CPU is disable
ACLK and SMCLK remain active
MCLK is disabled
And for LPM3:
CPU is disable
MCLK and SMCLK are disabled
ACLK remains active
As I see it ,I can not enter LPM3 cause the AP needs the SMCLK clock not to be disable? (cause the UART uses it)
Is that correct?
3) In F) , is it a proper way to call the TIMERA0 handler ? I perfrom TACRR0 = 10 , cause it is a small value which the timer will reach "in no time" just so it will enter the TIMERA0 handler to perform the task of sending the bytes of the string.
4) For the "roll back" in the AP: As I see it , the "flow" is like that:
enters LPM0 (main) --> UART gets interrputed --> exit LPM0 and goes to the UART handler --> when it is done reciving the bytes (usually 5) it enters LPM3 --> the timer finishes counting to TACRR0 value (which is 10) --> the TIMERA0 handler gets called --> when the TIMERA0 handler done sending the last byte it disables the timer (TACTL0 = MC_0;) --> we "roll back" to the instruction which got us to LPM3 within the UART handler --> ??
Now , does ?? is "rolling back" to the instrcution which took us to LPM0 within the main program , OR do we "stay here" (in the instruction that entered us to LPM3 within the UART handler E) ?
If we do stay on E) , do I need to change it to LPM0 cause , again, the UART uses the SMCLK which is NOT active in LPM3 but indeed active in LPM0 ?
5) Any other comments will be super !!
Thanks allot,
Guy.
1) This will work
2) When you config this:
UCA0CTL1 |= UCSSEL_2; // SMCLK
This mean that UART used SMCLK, SMCLK will stop when you make MCU turn to LPM3;so that
UART will not work, you should config UART use ACLK, this will make UART work in LPM3 mode.
3) ...
4) ...
5) See 2
I hope this will help you

What's in xcode console with scanf ,when want a number but input a char?

xcode 5.0
when I run following code:
void guessNum(){
int answer = 0;
int guess = 0;
int turn = 0;
answer = arc4random() % 100 + 1;
while (guess != answer) {
turn++;
NSLog(#"Guess #%i: Enter a number between 1 and 100", turn);
scanf("%i", &guess);
if (guess > answer) {
NSLog(#"Lower!");
}
else if (guess < answer) {
NSLog(#"Higher!");
}
else {
NSLog(#"Correct! The answer was %i", answer);
}
} // end of while loop
NSLog(#"It took you %i tries", turn);
}
when I type a character, just like a in xcode debug console, program run automatic and print:
...
2013-11-18 10:47:39.719 donglix[15115:303] Higher!
2013-11-18 10:47:39.719 donglix[15115:303] Guess #1932: Enter a number between 1 and 100
2013-11-18 10:47:39.719 donglix[15115:303] Higher!
2013-11-18 10:47:39.720 donglix[15115:303] Guess #1933: Enter a number between 1 and 100
...
what's the problem?
"scanf()" reads the input you've typed in and, because of your "%i" (integer) format string, is expecting to take that input and drop it into a number.
If you used "%s" as your format string, then you would take the input as a C-style character array (and have to convert those characters if you wanted to get the integer value out of that).
For example, you can replace this line:
scanf("%i", &guess);
with something like this:
char stringToConvert[256]; // if you type more than 256 characters, you'll crash
sscanf("%s",&stringToConvert);
guess = atoi(stringToConvert); // this function converts the string into an integer
If you type in the character "a", scanf converts that to 97 in the ascii table.

C++ srand function looping

I have the following method as part of a password generating program to generate a random password which is then validated.
My problem is that the srand function never meets the validation requirements and keeps looping back to create a new password.
Im posting the code below to ask if anyone has a more efficient way to create the random password so that it will meet validation requirements instead of looping back continously.Thanks.
static bool verifyThat(bool condition, const char* error) {
if(!condition) printf("%s", error);
return !condition;
}
//method to generate a random password for user following password guidelines.
void generatePass()
{
FILE *fptr;//file pointer
int iChar,iUpper,iLower,iSymbol,iNumber,iTotal;
printf("\n\n\t\tGenerate Password selected ");
get_user_password:
printf("\n\n\t\tPassword creation in progress... ");
int i,iResult,iCount;
char password[10 + 1];
char strLower[59+1] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRTUVWXYZ!£$%^&*";
srand(time (0));
for(i = 0; i < 10;i++)
{
password[i] = strLower[(rand() % 52)];
}
password[i] = '\0';
iChar = countLetters(password,&iUpper,&iLower,&iSymbol,&iNumber,&iTotal);
//folowing statements used to validate password
iChar = countLetters(password,&iUpper,&iLower,&iSymbol,&iNumber,&iTotal);
iUpper = countLetters(password,&iUpper,&iLower,&iSymbol,&iNumber,&iTotal);
iLower =countLetters(password,&iUpper,&iLower,&iSymbol,&iNumber,&iTotal);
iSymbol =countLetters(password,&iUpper,&iLower,&iSymbol,&iNumber,&iTotal);
iNumber = countLetters(password,&iUpper,&iLower,&iSymbol,&iNumber,&iTotal);
iTotal = countLetters(password,&iUpper,&iLower,&iSymbol,&iNumber,&iTotal);
if(verifyThat(iUpper >= 2, "Not enough uppercase letters!!!\n")
|| verifyThat(iLower >= 2, "Not enough lowercase letters!!!\n")
|| verifyThat(iSymbol >= 1, "Not enough symbols!!!\n")
|| verifyThat(iNumber >= 2, "Not enough numbers!!!\n")
|| verifyThat(iTotal >= 9, "Not enough characters!!!\n")
|| verifyThat(iTotal <= 15, "Too many characters!!!\n"))
goto get_user_password;
iResult = checkWordInFile("dictionary.txt", password);
if(verifyThat(iResult != gC_FOUND, "Password contains small common 3 letter word/s."))
goto get_user_password;
iResult = checkWordInFile("passHistory.txt",password);
if(verifyThat(iResult != gC_FOUND, "Password contains previously used password."))
goto get_user_password;
printf("\n\n\n Your new password is verified ");
printf(password);
//writing password to passHistroy file.
fptr = fopen("passHistory.txt", "w"); // create or open the file
for( iCount = 0; iCount < 8; iCount++)
{
fprintf(fptr, "%s\n", password[iCount]);
}
fclose(fptr);
printf("\n\n\n");
system("pause");
}//end of generatePass method.
I looked at your code at glance and I think I have found the reasons inspite of which validation requirements aren`t meet.
I suggest you to pay attention to the following parts of your code:
1) char strLower[59+1] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRTUVWXYZ!£$%^&*";
here you should add numbers 0..9, this is one of the reasons why requirements could not be met, because how number can be picked if it isn`t in the set of numbers from which you pick?!
replace it for ex. with:
char strLower[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRTUVWXYZ!£$%^&*0123456789";
2) password[i] = strLower[(rand() % 52)]; - and in this part of the code, replace 52 with total number of symbols in string from which you randomly pick numbers.
I recommend you to replace it with the following code:
password[i] = strLower[(rand() % (sizeof(strLower) / sizeof(char) - 1))];
you could alter your algorithm.
choose at random a number of Upper characeters that is above 2.
choose at random a number of Lower character that is above 2.
choose at random a number of Sybmol character that is above 1.
choose at random a number of Number characters that is above 2.
and then recompose your password with the random items, re-ordered at random. Fill with whatever character you want to pas the verifyThat predicates: >=9 and <= 15.
And please: don't use goto. Make function calls instead.

Resources