Loading [MathJax]/extensions/MathZoom.js

Thursday, 24 March 2016

Using a Servo

I've decided to see how much control I can add to the robot arm project so I bought a servo. This is a small motor that can be set to specific positions based on a signal. Such a device has 3 input lines, 2 for power and one for the signal.

First off, I wanted to use my new Ubuntu laptop to develop the Arduino code. Unfortunately, after installing the Arduino IDE and updating to version 1.6.7 I got the following error trying to upload the blink sketch:


avrdude: ser_open(): can't open device "/dev/ttyACM0": Permission denied

This is because in Ubuntu the current user isn't automatically given permission to the usb device. To grant permission I followed these steps

  1. whoami (get username)
  2. sudo usermod -a -G dialout username : Modify user, add to dialout group (allows access to serial ports via files in /dev)
  3. sudo chmod a+rw /dev/ttyACM0 : give '+' all users 'a' read/write 'rw' access to /dev/ttyACM

Now I was able to upload to the Ardunio I connected the servo, shown below
  • Brown : Groud
  • Red : + 5v
  • Yellow : S(ignal)

One thing I noticed, I had the servo plugged into SERVO_2 on the motor shield, conecting to SER1 resulted in the controller chip rapidly heating. Fortunately no damage was done.

I tried using the Sweep sketch with this and then the following

#include <Servo.h>

Servo servo;
void setup() {
  // Attach the servo on pin 9 to the servo object
  servo.attach(9);
}

void loop() {
   servo.write(20);
   delay(1000);

 
   servo.write(160);

   delay(1000);
}    


A problem with this setup was the servo sometimes would jitter or stall. I suspect this was due to interference from the Arduniop and related perhaps to automation in the loop. I managed to reduce this almost entirely by removing the sleeps from the above sample and setting the angle via serial input:

#include <Servo.h>

Servo servo;
void setup() {
  // Attach the servo on pin 9 to the servo object
  servo.attach(9);
  Serial.begin(19200);
  Serial.println("Ready");
}

void loop() {

  if (Serial.available())
  {
    char ch = Serial.read();

    switch(ch)
    {     
      case '1':
        servo.write(40);
        break;
      case '2':
        servo.write(60);
        break;
      case '3':
        servo.write(80);
        break; 
      case '4':
        servo.write(100);
        break;     
      case '5':
        servo.write(120);
        break;              
    }
  }
}


I was also happy with this because I'll be controlling from the Raspberry Pi in a similar way to this in the future.

Thursday, 17 March 2016

Supermarket planner updates

I recently fixed a bug in the Supermarket planner which was caused by a problem with the binding of XML to the DataGrid. This is a good point to explain how I did the binding and the problems solved.

The XML containing the data looks like this:

   <Meal name="Mushroom Omelette" type ="Vegetarian, Quick">
      <Ingredients>
        <Ingredient>Eggs</Ingredient>
        <Ingredient>Mushrooms</Ingredient>
        <Ingredient>Cheese</Ingredient>
        <Ingredient>Salad</Ingredient>      
      </Ingredients>
    </Meal>
    <Meal name="Lamb Chops + Veg" type="">
      <Ingredients>
        <Ingredient>Lamb Chops</Ingredient>
        <Ingredient>Brocolli</Ingredient>
        <Ingredient>Courgette</Ingredient>
      </Ingredients>
    </Meal>


The grid looks like this. For each <Meal> element there is a row with text from the name attribute.
Double clicking on the row expands the grid to show the ingredients. You can also edit these




I used the XmlDataProvider for binding, this needed to be in the Windows.Resources to be accessible by the save event.

<Window.Resources>
      <!-- Meal Data needs to be in the window resources so it can be accessed easily by the save event -->
      <XmlDataProvider x:Name="Meals" x:Key="MealData" Source="./Data/SuperMarketDataMeals.xml" XPath="/SuperMarketData/Meals/Meal"/>


The DataGrid xaml itself is shown below

The DataGrid ItemsSource is set to {Binding} with DataContent from the {StaticResource MealData} defined earlier.

I use a DataGridTemplate column for the rows, using {Binding XPath=name} for the text.

For the expanded details grid I use a RowDetailsTemplate with its own DataGrid, ItemsSource now with {Binding XPath=Ingredients/Ingredient}

The double click handler simply changes the DetailsVisibility flag on the clicked row:

var row = (DataGridRow)sender;
row.DetailsVisibility = row.DetailsVisibility == 

              System.Windows.Visibility.Collapsed ?
              System.Windows.Visibility.Visible :
              System.Windows.Visibility.Collapsed;

The bug was that when the row was minimised by double clicking, the grid details still contained the expanded row. This was manifested by dragging the next meal down across to the calendar grid. Instead of seeing that meal appear, the meal that had had its details shown was dropped instead. For example from the screen shot above, when the Omelette was minimised, dragging Lamb Chops for example would end up with the Omelette dropped.

To fix this, I needed to refresh the data grid when collapsing the details.

I needed to call CommitEdit first otherwise I would get a runtime exception "Refresh is not allowed during an AddNew or EditItem transaction"

if (row.DetailsVisibility == Visibility.Collapsed)
{
    mealGrid.CommitEdit(DataGridEditingUnit.Row, true);
    mealGrid.Items.Refresh();
}