Category Archives: Projects

Using PiPDP8 with a terminal

  1. Copy the file serial-getty@.service from /lib/systemd/system to /etc/systemd/system

  2. The file must be renamed, so that it points to your serial terminal which will be ttyUSB0. The filename becomes:
    serial-getty@ttyUSB0.service

  3. The file may need to be edited with the parameters of your serial terminal, or the default setting may work.
    In my case I changed the first line in the [Service] section to read: ExecStart=-/sbin/agetty ttyUSB0 9600 vt100

  4. Now, enable the service with:

sudo systemctl enable serial-getty@ttyUSB0.service

You should get a Creating sim link …​. message. The service will now start up at every boot.

Note
The serial-getty@service file is a generic template for setting up a serial terminal with a log-in prompt.


An approach to writing Arduino code

Code Review

Let’s do an example of code development.

Let’s say that we are reading analog values for ranges and want to make decisions based on ranges to set ranges of values. We start with the following snippet. The `if` statements quickly become wordy and program flow maybe starts to become unclear.  So lets look at some ways to unravel this with a subroutine.


reading = analogRead(1);

int state = 0;

if (reading > 0 && reading < 500){ 
state = 1; 
} 

if( reading > 499 && reading < 700) { 
state = 2; 
} 

if ( reading > 699  && reading < 1025) {
 state = 3;
}

You could just write a small procedure  to simplify this comparison test series…


bool inRange(int x, int y, int z){

 if (x => y && x <= z) {
      return true;
     } else {
      return false;
     }
}

and then call it with much easier to read process requests… like the following code.


//file inrange.ino

// State 1: Connect analog pin to gnd
// State 2: Connect analog pin to 3.3V
// State 3: connect analog pin to 5V

int reading;
int state = 0;

void setup() {
  // put your setup code here, to run once:
 Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
reading =  analogRead(1);

  if(inRange(reading,0,500))
     state = 1;
  
    if(inRange(reading,500,700))
       state = 2;
    
      if(inRange(reading,700,1024))
         state = 3;
      
    Serial.print("Reading ");
    Serial.println(reading);
    Serial.print("state: ");
    Serial.println(state);
    delay(1000);
}

//-------------------------------------------------
// Notice the use of non-informative variable names
// we should fix this.

int inRange(int x, int y, int z){
   bool val;
   if (x >= y && x <= z) {
      val =  true;
    } else {
      val = false;
    }

    return(val);
  }


See? You really get some better logic flow this way.

New lets go a step further… using space saving `const` or constants.


// File: inrange1.ino

// State 1: Connect analog pin to gnd
// State 2: Connect analog pin to 3.3V
// State 3: connect analog pin to 5V

//=====[ CONSTANTS ]============================================================
//Still a bit wordy here...
const int RED = 0;
const int GREEN = 1;
const int BLUE = 2;

//=====[ PINS ]=================================================================
int anPin = 1;


//=====[ VARIABLES ]============================================================
int reading;
int state = 0;



void setup() {
  Serial.begin(9600);
  // Wait for USB on Leonardo and similar devices
  while (!Serial) {
  }

}

void loop() {
  reading =  analogRead(anPin);
  
  // debugging code...
  Serial.print("Reading ");
  Serial.println(reading);



  if (inRange(reading, 0, 499)) 
    state = RED; 
    
  if (inRange(reading, 500, 699)) 
    state = GREEN;
  
  if (inRange(reading, 700, 1024)) 
    state = BLUE;
    
  ColorState();

  delay(1000);
}

//==============================================================================

int inRange(int passVal, int minVal, int maxVal) {

  if (passVal >= minVal && passVal <= maxVal) {
    return true;
  } else {
    return false;
  }
}
//==============================================================================

void ColorState() {
  Serial.print("State: ");

  switch (state) {
    case RED:
      Serial.println("Red");
      break;
    case GREEN:
      Serial.println("Green");
      break;
    case BLUE:
      Serial.println("Blue");
      break;
    default:
      break;

  }
}

Now we start to see how to break out sections of code into useful re-usable subroutines. So lets take this one step further and refine it into a final version using the `enum` command. Notice how the code becomes even a tiny bit simpler.


// File: inrange3.ino

// State 1: Connect analog pin to gnd
// State 2: Connect analog pin to 3.3V
// State 3: connect analog pin to 5V


enum States {
  RED,
  GREEN,
  BLUE
};

States state = RED;  // use the enumeration and initialize to RED

//=====[ PINS ]=================================================================
int anPin = 1;


//=====[ VARIABLES ]============================================================
int reading;

void setup() {
  Serial.begin(9600);
  // Wait for USB on Leonardo and similar devices
  while (!Serial) {
  }

}

void loop() {
  reading =  analogRead(anPin);

  if (inRange(reading, 0, 499))
    state = RED;

  if (inRange(reading, 500, 699))
    state = GREEN;

  if (inRange(reading, 700, 1024))
    state = BLUE;

  ColorState(state);

  delay(1000);
}

//==============================================================================

int inRange(int passVal, int minVal, int maxVal) {

  if (passVal >= minVal && passVal <= maxVal) {
    return true;
  } else {
    return false;
  }
}

//==============================================================================

void ColorState(int range) {
  Serial.print("Condition: ");

  switch (range) {
    case RED:
      Serial.println(" Red");
      break;
    case GREEN:
      Serial.println(" Green");
      break;
    case BLUE:
      Serial.println(" Blue");
      break;
    default:
      break;

  }
}


So while this is not the best code, it definitely accomplishes the simplification goal in the main process loop.

Food for thought.

Creating a weather station with Linux

Long ago I decided that I wanted to keep track of local weather. This is somewhat related to my desire to keep an eye on my raised bed gardens during the summer and partially due to my desire to have fun electronics projects to keep me doing “fun things”. I had already started with 1-wire and had a few devices that I either purchased or made myself.

As a first pass, I decided to see if I could get all my sensors working under Linux before attempting the Arduino weather station  conversion.  That said, It would have been easier if I had decided to use Windows and follow Tim Bitson’s examples from his “Weather Toys” book. The book provides guidance for MacOS and Windows only. That’s really not a show stopper though as I was able to get everything working.

Step 1: Install Linux

Install Ubuntu Linux workstation version 9.10 LTS (I tried newer versions but they have some annoying issues)

Step 2: Installing JavaVM and RXTX

Note: A version of Java is installed by default, It’s just not the one I want.

I installed the full suite of latest SUN JAVA (not default OPENJDK and note that the SUN install requires enabling partner repositories – Google for instructions about enabling and then the JAVA install is simple)

Install RXTX with the command

sudo apt-get install librxtx-java

(It does all the tricky bits for you)

Step 3: OneWire support for JAVA

Download OneWireAPI “http://files.dalsemi.com/auto_id/public/owapi_1_10.zip
Extract contents  to a convenient location and get setup to copy files.
Copy the file OneWireAPI.jar to /usr/share/java/OneWireAPI.jar

The Java Libraries get installed to /usr/share/java. This is default behavior for librxtx-java install, so I used the same solution for OnewireAPI (manually copied)

Step 4: NETBEANS

In my case, this is version 6.8, installed from Synaptic Installer or you could use:

sudo apt-get install netbeans

Netbeans will create a project directory by default in your home folder. Your code goes here.

Libraries:
When defining the library settings for NETBEANS, it’s as simple as the two entries in the “libraries” section, as shown in the book.
a) /usr/share/java/OneWireAPI.jar
b) /usr/share/java/RXTXcomm.jar

Step 5: Grab WEATHERTOYS code.

Here

General Notes

I use the AAG TAI603B interface (USB-SERIAL & 1 Wire Power Injector with home made Hobby Boards adapter) and this is automatically recognized as a device by this version of Linux. In my case, it is a serial device, coded as:

public static final String ONE_WIRE_SERIAL_PORT = "/dev/ttyUSB0";

and seen by the API as:

public static final String ADAPTER_TYPE = "DS9097U";

You can find the ports available with the following command:

sudo dmesg | grep tty

You will likely see something like:

"/dev/ttys0" or  "/dev/ttyUSB0"