Drawing a bounding box over an image with C#/.net and WinForms

Most of the info in this post can be found between the following two links:

http://stackoverflow.com/questions/2065162/filled-rubber-band-in-winforms-application

https://msdn.microsoft.com/en-us/library/3t7htc9c(v=vs.110).aspx

Drawing a bounding box over an image to select a region took me longer to figure out than I expected. Here’s a brief bare-bones example demonstrating how to do it.

To follow along, pop a PictureBox form inside of a form, and set a background image. Make sure you can run the program and see this work as expected.

What’s next is pretty straightforward. First you need to create callbacks for the mouse down and mouse up events captured by the PictureBox. We’ll need to set a value in the main form class to indicate that the mouse is currently down.

secondstepprogress

 

The way this is going to work is that on the MouseDown event, the location of the mouse is going to be stored, and we’ll also store the current point of the mouse as it moves around (while the mouse button is still held down). Using those two points, we’ll draw a box.

Next let’s update the MouseDown callback to include capturing the initial mouse down point, and also add a MouseMove callback to update the current point.

thirdstepprogress

 

Now it’s time to do the actual drawing of the box. This is done by making a callback for the Paint event that the PictureBox receives whenever it’s “dirty”. Inside that callback is where the rectangle drawing happens. We’ll trigger this Paint event manually by calling the Invalidate() method on the PictureBox in the MouseDown, MouseUp, and MouseMove callbacks, too.

Here it is all together.

finalstep

Here is a Gist: https://gist.github.com/anonymous/6788f9f3095ed40ec06b4f5795c2d1c2

And here’s the final result. You’ll have to imagine the mouse cursor on the bottom-right of that red box since printscreen doesn’t capture it.

result

I usually try to put the code inline with the post, but I got frustrated fighting the WordPress code formatting! The context for this post is that I made a toy Mandelbrot fractal viewer and I wanted to draw a box around an area I wanted to zoom into.

Posted in Uncategorized | Leave a comment

Control a power strip with an Arduino

I’m running some tests at the office that require cycling the power to a device. After spending a few days doing this manually by flipping the switch on a power strip, I started searching for a better way.

Some Googling revealed the IoT Power Relay made by a company called Digital Loggers.

It’s got a +/- screw terminal on the side (the green part) that can be connected directly to an Arduino digital output and ground. Raise the Arduino output high, and two plugs turn on while two others turn off. Perfect!

iotrelay

I control the output on the Arduino through a program that handles all of the test (logging, etc). The Arduino sits in a loop waiting for serial input. If the Arduino program sees “A” come across the serial line from my testing program on the PC, it raises the output high, powering off my device that is plugged it into the “Normally ON” plug. Four seconds later, the Arduino output is set low, powering my device back on.

Pretty slick. I’m glad it worked – Plan B was to hot glue some servos to my power strip to toggle the power switch!

Posted in Uncategorized | 1 Comment

Passing a ctypes array of struct from Python to .dll

I’m working on a small project that requires interfacing Python to a C .dll. I’ve never had to pass an array of structures by reference before with ctypes, so here’s a quick sanity check I did to make sure I was doing it right before diving into something heavier.

The .dll source:

// structtest.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"

#ifdef STRUCTTEST_EXPORTS
#define STRUCTTEST_API __declspec(dllexport)
#else
#define STRUCTTEST_API __declspec(dllimport)
#endif

extern "C" {
	struct structtest {
		char x;
		int y;
		long z;
	};
	
	STRUCTTEST_API void fillonestruct(struct structtest *t)
	{
		t->x = 'A';
		t->y = 1234;
		t->z = 5678;
	}

	STRUCTTEST_API void fillmultiplestruct(struct structtest *t, int n)
	{
		for (int i = 0; i < n; i++)
		{
			t->x = (char)((int)'A' + i);
			t->y = i;
			t->z = i;
			t++;
		}
	}
}

Here’s the Python program that uses the .dll:

from ctypes import *

class structtest(Structure):
    _fields_ = [("x", c_char),
                ("y", c_int),
                ("z", c_long)]

if __name__ == "__main__":
    n_struct2 = 5
    lib = CDLL("structtest.dll")
    
    struct1 = structtest()
    struct2 = (structtest * n_struct2)()
    
    print("Before passing to .dll")
    print("Struct1 x:{} y:{} z:{}".format(struct1.x, struct1.y, struct1.z))
    for i in range(n_struct2):
        print("Struct2[{}] x:{} y:{} z:{}".format(i, struct2[i].x, struct2[i].y, struct2[i].z))
    
    lib.fillonestruct(byref(struct1))
    lib.fillmultiplestruct(byref(struct2), c_int(n_struct2))
    
    print("\nAfter passing to .dll")
    print("Struct1 x:{} y:{} z:{}".format(struct1.x, struct1.y, struct1.z))
    for i in range(n_struct2):
        print("Struct2[{}] x:{} y:{} z:{}".format(i, struct2[i].x, struct2[i].y, struct2[i].z))

The output:
Before passing to .dll
Struct1 x: y:0 z:0
Struct2[0] x: y:0 z:0
Struct2[1] x: y:0 z:0
Struct2[2] x: y:0 z:0
Struct2[3] x: y:0 z:0
Struct2[4] x: y:0 z:0

After passing to .dll
Struct1 x:A y:1234 z:5678
Struct2[0] x:A y:0 z:0
Struct2[1] x:B y:1 z:1
Struct2[2] x:C y:2 z:2
Struct2[3] x:D y:3 z:3
Struct2[4] x:E y:4 z:4

So hooray – everything works as expected.

Posted in Hobbies, Programming, Technology | Leave a comment

ADXL335 Accelerometer on an Arduino

I picked up an ADXL335 accelerometer in a packaging designed to fit onto a solder-less breadboard so that I could interface it to my Arduino. I had a few time-consuming problems interfacing with it because I’m not used to reading chip data sheets.

My assumption was that you’d deliver voltage to it, and it would spit out an analog signal that could be easy translated to acceleration using some constant factor. This isn’t exactly the case. The output resolution, milliVolts per g (1 g = Earth gravity), and voltage bias, is dependent on the voltage delivered to the power pin. I think in hindsight this makes sense, but the data sheet phrases this, and a few other things very peculiarly. I’m fairly inexperienced reading chip data sheets.

The data sheet is here (PDF). On the third page is pretty much everything you need to know to get useful data out of it, and the rest of the doc is stuff most hobbyist level people don’t care about, like how it behaves in different temperatures, and noise expectancy.

The phrase “RATIOMETRIC” shows up a few times. What this means is that a few of the specs are dependent on the power delivered to the chip. The sensitivity (mV/g) is stated to be ratiometric, and the example they give is that when you deliver 3V to the power supply, the sensitivity is 300 mV/g. In a later section called “Use with operating voltages other than 3V” it gives the example of 360 mV/g with a 3.6V power supply, and 195 mV/g with a 2V power supply. You can pretty much gather that the sensitivity in mV/g is the power supply voltage divided by 10. More or less.

Another ratiometric value is the “0g bias”. I don’t do a whole lot of analog electronics stuff, so this took me a bit to figure out. The accelerometer chip can detect negative acceleration, but it doesn’t output a negative voltage signal. What you do is consider the middle point of the power supply voltage range the 0 point. My power supply voltage is 3.3V, so I have to treat 1.6V as the zero point. You’ll add have to subtract that zero point from any voltage reading to get the actual mV/g value.

Here’s some numbers to drive the point home. My power supply is 3.3V, which is 3300 mV. 3300 divided by 10 is 330, so the chip is going to deliver 330 mV per 1g of acceleration. If I have the module on my table with the z-axis point up, it’s going to have 1g of acceleration applied to it, since it’s going to just read the pull of the Earth’s gravity and no other force. The chip’s zero point is the middle of the power supply range, 1.6V (1600 mV), so the actual voltage value it’s going to output for 1g of acceleration is 1930 mV, or 1.93 Volts. Since I know all this, I only need to subtract the zero point voltage to get the true value of 330 mV.

If I turn my accelerometer upside-down, it’s going to feel -1g of force. The voltage it would output would be 1.27V. When you subtract the zero point voltage you get -330 mV, which comes out to -1g.

Anyways, here’s the Arduino code that gets values for the X, Y, and Z axis spit out in units of g.

//Quick accelerometer test
//X is on A0; Y is on A1; Z is on A2

//Analog input pins 0, 1, and 2
//are what I send the x,y, and z
//accelerometer outputs to, respectively
int xAxisPin = A0;
int yAxisPin = A1;
int zAxisPin = A2;

//Variables to hold the returned
//ADC data from the analog input
//pins
int xAxisValADC = 0;
int yAxisValADC = 0;
int zAxisValADC = 0;

//Variables to hold the voltage
//values after converting from ADC
//units to mV
float xAxisValmV = 0;
float yAxisValmV = 0;
float zAxisValmV = 0;

//My Arduino Uno has a 10-bit
//AD converter, with a max value
//of 1023
int ADCMaxVal = 1023;

//The AD converter voltage
//is powered by 5V
float mVMaxVal = 5000;

//I measured the power going to the
//accelerometer as actually being 
//3230 mV, so I use this value to 
//define the mid-point
float supplyMidPointmV = 3230 / 2;

//Since the supply is actually 3230
//mV, I know the output will be 323mV
//per 1g detected
int mVperg = 323;

//Multiply any acquired ADC value
//by mVPerADC to convert to mV
float mVPerADC = mVMaxVal / ADCMaxVal;

void setup()
{
  Serial.begin(9600);
  
  //I don't know if setting them to
  //input is necessary, but I do it
  //anyways.
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
  
}

void loop()
{
  //Read the x, y, and z values from
  //the analog input pins
  xAxisValADC = analogRead(xAxisPin);
  yAxisValADC = analogRead(yAxisPin);
  zAxisValADC = analogRead(zAxisPin);
  
  //Convert the ADC values to millivolts
  xAxisValmV = xAxisValADC * mVPerADC;
  yAxisValmV = yAxisValADC * mVPerADC;
  zAxisValmV = zAxisValADC * mVPerADC;
  
  //This could be prettier. What's happening is the mid-point
  //voltage value is subtracted from the voltage recorded
  //from the analog input, and then that value is divided
  //by how many millivolts per g the accelerometer is
  //ouputing. This results in the value being printed
  //in units of g.
  Serial.print((xAxisValmV - supplyMidPointmV) / mVperg);
  Serial.print("\t");
  Serial.print((yAxisValmV - supplyMidPointmV) / mVperg);
  Serial.print("\t");
  Serial.print((zAxisValmV - supplyMidPointmV) / mVperg);
  Serial.print("\t");   
  
  Serial.println();
  
  delay(100);
}

It’s a bit verbose, but I wanted to be super clear about what is going on.

I dumped 20 seconds of gathered data into a .txt file and used Excel to make this pretty graph.

accelchart

For the first few seconds it’s just sitting on the table, so the z-axis is at 1g, and the x and y-axis are at about 0 (these aren’t calibrated readings, but it’s good enough). You can see when I pick it up and shake it around a bit, then put it back on the table. Neat.

The motivation for writing this post is because it took me about an hour to reconcile the info in the data sheet with the values I was reading on the analog inputs. It was hard to find anything useful online that stated plainly what you need to do on the Arduino end. Hopefully this helps someone out.

Post a comment or message me on Twitter (@cheydrick) if you have any questions.

Posted in Uncategorized | Tagged | 24 Comments

Brief Example of Calling .dll Functions in C#

I don’t like C#, but the free version of Visual Studio only lets you use the interface builder in C#/.net programs, so here we are. My goal was to cheat and write the interesting parts of the program in C/C++, compiling to a .dll, and calling it from C#.

This has turned out to be an ordeal.

I have a great handle on calling functions in a .dll from Python. The CTypes module is amazing, and incredibly well documented. C# has a module (service?) in the System.Runtime.InteropServices namespace and the Platform Invoke service for “consuming un-managed code”, but it has been a real pain getting it to work.

I’ll admit that 80% of the problem is that I’m still fairly new to C#, but there is no shortage of information online for vanilla C# programming. Interfacing to a .dll seems to be uncommon enough that it’s hard to find exactly what I’m looking for when I run into a use-case that hasn’t been discussed much.

Here’s what I’m getting at. Let’s say I have a function in my .dll as such:


INTEROPSTRUCTTEST_API int GetInteger()
{
	return 42;
}

Here’s what the function in C# would look like for interfacing with GetInteger() in the .dll (which I put in a class called InteropStructTestDLLWrapper):

[DllImport(&quot;InteropStructTest.dll&quot;)]
public extern static int GetInteger();

And here’s how to call that in C#:

int int_from_dll = 0;
int_from_dll = InteropStructTestDLLWrapper.GetInteger();

This behaves exactly as you would expect – it returns the number 42. Things start getting weird when pointers are involved.

Function in .dll:

INTEROPSTRUCTTEST_API void PassIntegerPointer(int *i)
{
	*i = 27;
}

Function for calling the .dll function in C#:

[DllImport(InteropStructTest.dll, CallingConvention = CallingConvention.Cdecl)]
public extern static void PassIntegerPointer([In, Out]ref int i);

Calling the function in C#:

InteropStructTestDLLWrapper.PassIntegerPointer(ref int_from_dll);

Now you have to deal with [In, Out] and ref, and CallingConvention.Cdecl. Much of this was guess-and-check to get working using information I gleaned from dozens of StackOverflow posts and other blogs. Things start getting extra weird when you want to pass a pointer to a struct or array of structs.

I decided it was best to just start making a sample .dll and .cs program that demonstrated a clear use-case for passing various data types to and from a .dll. Something that I could reference and add to as I learn. So far it has returning integers, passing a pointer to integer to be modified, passing a pointer to a struct to be modified, and passing an array of structs to be modified (which was super hard to find anything online about).

https://github.com/cheydrick/CSInteropStructTest

Right now it has examples of all the things I’ll have to do in small side-project I’m working on. I’ll flesh it out as needed.

Hopefully I’ll save someone some time. I’m embarrassed at how much time I burned getting this far!

Posted in Hobbies, Programming, Technology | Tagged , | Leave a comment

C# Struct Sizes

I’ve been banging my head against trying to get C# to talk to a .dll written in straight C for the past few days. I finally got a grip on passing basic data types, and pointers to basic data types, to/from my .dll, but I started getting garbage when passing pointers to structs and arrays of structs.

I wrote a master sanity check C# program and C .dll to demonstrate the correct methods for getting structs, pointers to structs, and arrays of structs into the .dll functions, and as soon as I clean it up and comment it I’ll post it.

One of my favorite sanity check tools in C is the sizeof() function, which tells you the size in bytes of a data type or struct. Well, C# has a sizeof() function, too, but it requires some verbosity to get the size of a struct out of it. It must have something to do with C# structs being memory managed. There are a few StackOverflow posts and other blog posts about how to do this, but they’re all overly complex or beyond the scope of simply getting the struct size, so here’s my take on it.

Here’s a small program that demonstrates how to get the size of C# structures.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace CSStructSize
{
    class Program
    {
        public struct SimpleStruct
        {
            public int firstInt;
            public int secondInt;
        }

        public struct ComplexStruct
        {
            public char firstChar;
            public char secondChar;
            public long firstLong;
            public short firstShort;
            public char thirdChar;
            public char fourthChar;
        }
        
        static void Main(string[] args)
        {
            Console.WriteLine("\nSize of C# char is: {0}", sizeof(char));
            Console.WriteLine("Size of C# short is: {0}", sizeof(short));
            Console.WriteLine("Size of C# int is: {0}", sizeof(int));
            Console.WriteLine("Size of C# long is: {0}", sizeof(long));
            Console.WriteLine("Size of SimpleStruct: {0}", Marshal.SizeOf(typeof(SimpleStruct)));
            Console.WriteLine("Size of ComplexStruct: {0}", Marshal.SizeOf(typeof(ComplexStruct)));
            Console.ReadLine();
        }
    }
}

The output is:


Size of C# char is: 2
Size of C# short is: 2
Size of C# int is: 4
Size of C# long is: 8
Size of SimpleStruct: 8
Size of ComplexStruct: 24

Posted in Uncategorized | Leave a comment

File Open Dialog Box in Python

I’m putting the finishing touches on a side project at work that requires opening a file as an argument at the command line, or through a file open dialog box. Here’s a snippet that demonstrates how I implemented it.

 

import sys
import os

def choose_file():
    try:
        import Tkinter, tkFileDialog
    except ImportError:
        print "Tkinter not installed."
        exit()
    
    #Suppress the Tkinter root window
    tkroot = Tkinter.Tk()
    tkroot.withdraw()
    
    return str(tkFileDialog.askopenfilename())
    
if __name__ == "__main__":
    
    #If no file is passed at the command line, or if the file
    #passed can not be found, open a file chooser window.
    if len(sys.argv) < 2:
        filename = os.path.abspath(choose_file())
    else:
        filename = os.path.abspath(sys.argv[1])
        if not os.path.isfile(filename):
            filename = choose_file()
            
    #Now you have a valid file in filename

It’s pretty straightforward. If no file is passed at the command line, or if the file passed at the command line isn’t a legitimate file, a file chooser dialog box pops up. If Tkinter isn’t installed, it bails out with an error message.

The bit about suppressing the Tk root window prevents a small box from appearing alongside the file chooser dialog box.

 

Posted in Programming | Leave a comment

FlightGear panic button with an Arduino

I like flight simulators, but I’m not very good at them. What I need is a panic button that puts me at a safe altitude for recovery. Fortunately the flight simulator I’m playing right now, FlightGear, has a way to get and set internal properties over a socket interface. There are some super big problems I ran into that aren’t well documented (or documented at all) in FlightGear’s wiki pages on the subject, and I go over those at the end.

Here is how I used my Arduino Uno to create a panic button that immediately sets my altitude to 9000 feet (there’s a video of it in action at the bottom of this post).

For a quick crash course in FlightGear’s property tree, start FlightGear with the “–httpd=5480” option and point a web browser (on the same machine) to http://localhost:5480. You can click through all the properties, and also set them right in the browser. Navigate to /position/altitude-ft and enter in 9000 (and click “submit”). This is pretty much what we’re going to do with the button, but instead of using the httpd interface we’ll be doing it over a network socket.

First thing is to create an XML file defining what properties we want exposed for manipulation. There’s a “generic” protocol that FlightGear uses for this. You can see an example near the bottom of http://wiki.flightgear.org/Property_Tree/Sockets. Here’s what mine looks like for the panic button:


<?xml version="1.0"?>
<PropertyList>
<generic>
 <input>
 <line_separator>newline</line_separator>
 <var_separator>tab</var_separator>

<chunk>
 <node>/position/altitude-ft</node>
 <name>altitude</name>
 <type>int</type>
 <format>%i</format>
 </chunk>

</input>
 </generic>
</PropertyList>

Call it “setaltitude.xml” and put it in the FlightGear\Data\Protocol directory.

Here’s the Arduino code for handling the button press. It’s not all that interesting – it just detects the button press and sends a serial message. The delay is to prevent button bounce from generating a ton of serial messages.


const int buttonPin = 2;

int buttonState = 0;

void setup()
{
 pinMode(buttonPin, INPUT);
 Serial.begin(9600);
}

void loop()
{
 buttonState = digitalRead(buttonPin);

 if (buttonState == LOW)
 {
 Serial.print("Pressed\n");
 delay(500);
 }

}

Here is a small Python program that acts as the middle-man between the Arduino and FlightGear. It intercepts the serial message and then sends the desired altitude to FlightGear over a socket.


from serial import Serial
from socket import *

ser = Serial('/dev/cu.usbmodemfd121', 9600)
s = socket(AF_INET, SOCK_STREAM)
s.connect(('192.168.1.5', 5500))

while(1):
 if (ser.inWaiting() > 0):
 serialRead = ser.readline()
 print "Read: " + serialRead
 s.sendall('9000\n')

Before I go over tying it all together I want to lay out two problems I had.

1) The XML file lets you define the properties you want to set, and the type of data (integer, float, string) that it is. I thought that this meant you needed to deliver the data in that way, too. I spent a lot of time getting erratic behavior from FlightGear because I was packing the altitude as binary data before sending it across. Regardless of the data type described in the XML file you need to send the data as a simple string terminated by the line_ separator defined.

2) I had assumed that FlightGear always acted like the server when the socket interface was enabled. This is incorrect (and again… not documented as far as I can tell). If you’ve set FlightGear’s socket interface as input you need to write the program delivering the data as the client. If you’ve set FlightGear’s socket interface as the output, you need to write your data receiving program as the server. Since I’m setting the socket interface as an input I have written my Python program as the client and it MUST be run after starting FlightGear, or you’ll get an error. I have no idea what the behavior is if you set the socket to be bi-directional.

To tie it all together, start FlightGear with the socket interface enabled and set to use the XML file as a generic description of what we want to send to FlightGear. Then start the Python program. It will sit and wait for a serial command from the Arduino and then send FlightGear the altitude. I set the rate at 5 Hz since I’m not really sending a lot of data rapidly.

This is what my settings (in Windows) looks like for FlightGear.

fgoptions

Here’s the button in action.

I’ve already gone the next step and interfaced a potentiometer for controlling the rudder. I’ll go over that in a future post, but I want to mention it now because I ran into bit of a problem. It was my intention to add this rudder control to the button program, but I discovered that if you have two property inputs defined in the XML file (in this case the altitude and the rudder position) you MUST send two values over the socket every time you update one or both values. The implication here is that every time I send rudder values I have to send an altitude. This is obviously impractical since I don’t want to alter the altitude all the time. I had hoped there was a value I could pass (such as an empty string) that would indicate “don’t update this value”, but no such luck. The only solution I can think of is to not mix control surface manipulation with flight model manipulation. The other solution would be to implement a bi-directional protocol and be constantly reading the altitude so that I know what the current altitude is and can send it along with the rudder values. This might cause very bad behavior if I can’t get and send the altitude value faster than the flight model changes it.

I like FlightGear, but the nearly nonexistent documentation is preventing me from loving it. It’s open source and the source is very well organized and clean, which is the only reason I figured out the solutions/workarounds to the problems I described above. Visually it’s behind the times, but that’s forgivable. It takes 58 seconds to start on both of my machines which have wildly different specs. I know it’s got a lot of terrain and stuff to parse through, but still.

Posted in Hobbies, Programming, Technology | Leave a comment

How to revive a dead character in Baldur’s Gate:EE

This took me forever to figure out. Xzar died on me early in the game and I couldn’t figure out how to revive him at a temple (which is what a few Internet sources said to do).

You must go to the priest, then select the dead characters headshot (or whatever the images on the right are called). Only then will the “Raise Dead” option be available (not red).

20121208-225155.jpg

Posted in Technology | 1 Comment

How to read serial data from an Arduino in Linux with C: Part 4

Parts one, two, and three dealt with non-canonical reading of serial data coming from an Arduino. Part 4 is how to do it in canonical mode.

I programmed the Arduino to wait until it receives a byte from the PC and then transmit “Hello” back. The (super simple) Arduino sketch is here: https://gist.github.com/2980344

I’m frustrated with the WordPress code posting functionality, so I put the program that does the reading to and receiving from the Arduino on Github. It’s called Canonical Arduino Read.

Here’s a breakdown of the important bits:


/* open serial port */
 fd = open("/dev/ttyACM0", O_RDWR | O_NOCTTY);
 printf("fd opened as %i\n", fd);

 /* wait for the Arduino to reboot */
 usleep(3500000);

As I’ve said before, you have to give the Arduino some time to reboot after you call open(). Notice that I’m opening this as a blocking port by leaving out O_NDELAY as an option.


/* get current serial port settings */
 tcgetattr(fd, &toptions);
 /* set 9600 baud both ways */
 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;
 /* Canonical mode */
 toptions.c_lflag |= ICANON;
 /* commit the serial port settings */
 tcsetattr(fd, TCSANOW, &toptions);

Nothing fancy here. I’m getting the current port configuration, setting the input/output speed to 9600 baud, setting the data expectations to be 8 bits per word, with no parity bit and no stop bit, setting canonical mode, and then committing those changes back to the serial port.

My past few posts have been about trouble I’ve had reading data, and the fixes were all in the code above that determines the serial port settings. I accidentally (by virtue of a sloppy copy/paste of another program I wrote) had  “&= CS8” instead of “|=CS8”. That was dumb mistake number one. Number two was that I was setting c_iflag to ICANON instead of c_lflag. That’s a TOUGH typo to catch.


/* Send byte to trigger Arduino to send string back */
 write(fd, "0", 1);
 /* Receive string from Arduino */
 n = read(fd, buf, 64);
 /* insert terminating zero in the string */
 buf[n] = 0;

printf("%i bytes read, buffer contains: %s\n", n, buf);

This last part of the program writes out one byte to the Arduino. The Arduino sees this, and then writes back “Hello”. I read that “Hello” into my buf[] array, and then terminate that array with 0 so that when I use printf() on the next line it doesn’t go into undefined parts of the array.

And that’s that. I started working on this as part of a larger project on Thursday. It’s Sunday evening now and I finally got this one part working perfectly. I don’t regret getting so stuck. I’ve had to really dig into the terminal interface and I feel much more confident with it now. Now that this chunk of code is working, I’ll fit it into the larger program.

The larger program will query the Arduino, and the Arduino will send back a voltage read from a temperature sensor. Super similar to what I’m doing above, which queries the Arduino (by sending it a byte) and gets serial data back. The next hump will be figuring out how to convert the string sent back into a numeric type like float or int. I don’t recall Unix having a standard ascii-to-int function. No doubt this is a solved problem, so I won’t have to search too hard to find a solution.

Leave a comment below or shoot me a message on Twitter @cheydrick if you have questions!

Posted in Hobbies, Programming | 14 Comments