Category Archives: Barometer Project

The stages of my Barometer Project

Write/Read a file in Python

In this blog, I am simply wanting to write some data to file so that my program can read it during  a subsequent restart.

I’m running Python 3 under Raspbian on a Raspberry Pi computer, so I am only going to deal with that system.  I shall ignore the complexities of input/output as far as possible.

Python holds its variables in many different formats such as text, integer, floating point and binary.   I want to store some integer values from a list variable and then to read them back at some future time.

The first step is to tell the system the name of the file and the directory where I want to store it.   The directory can be on any resource that I can access from the Pi, but in this case I will store it in the Pi’s Downloads directory. I will store the full path and file name (motorPosition.text) in a variable called logfile, using the statement:

logfile='/home/pi/Downloads/motorPosition.text'

Now I need to open the file with the parameter ‘w+’ which means it is opened for writing, as shown below.  The file will be created if it does not already exist. If it does exist, any contents will be deleted when the file is opened.  (If I want the new contents to be added, then I need to use the ‘a’ (append)  parameter instead of w+.  Note that the open command can fail for a variety of reasons, but as we aren’t trapping  errors, this would make execution halt.

Next we create a string of text.  MotorPos is a list of integer values, so  the for loop takes each value from the list, converts it to a string and appends it to the string called text.  Each value is followed by a newline character (‘\n’).  This will mean that each value will be on a separate line in the file.

When all the values in the list have been added to the string, the for loop terminates and the next statement writes the text to the file.

The next line closes the file.  This is important as it ensures that the output buffer is flushed and the system resources are released.

file = open(logfile,'w+') # store motorPos on SD card
text=''
for line in motorPos:
  text = text+str(line) +'\n' #append values to string

file.write(text) # write string to file
file.close() # flush buffer and release resources

Next we are going to try to read the values back into the list, using a try structure to trap a FileNotFound error.  If the file is present, it is opened for reading and a for loop reads lines 0 to 6 into motorPos, converting each string value to an integer.  It prints the result and then closes the file. (For reasons best known to its authors, range loops stop when the parameter reaches the upper limit rather than when it exceeds the upper limit.)

However, if the file does not exist, the program takes the necessary action (in this case, it is simply to pass control to the next statement).  Without the try structure, execution would terminate if the file is not present.

try: # Use motorPos positions from file if present
   file = open(logfile,'r+')

   for line in range(0,7):
      input_text = file.readline() 
      motorPos[line] = int(input_text)
   print (motorPos)
   file.close()
except FileNotFoundError: # File not present
   pass

Input/output is error-prone on any computer system and it is important to trap errors, otherwise programs will often fail for reasons that are unfathomable to the ordinary user.

I’m sure that Python aficionados will point out more elegant ways of doing this, but this is the most obvious way that I could fathom.  The documentation is quite fragmented, so that many sophisticated features are quite obscure.

Editing the file

You can read the file using the Pi’s built-in text editor.  It will look something like this:

8
516
404
472
592
1824
180

You can then edit the file, which could be used to supply starting parameters to the program.  However, you will only be able to save the updated file if you have the necessary permissions, generally if you are the owner.  I have found that if I let the program create the file, then I can view and copy the file but cannot save an update.  However, if I create the file first using the text editor, then the program can write to it and I retain permissions to update it.  This is just one of the complexities of input/output that i mentioned previously.  Of course, file permissions can be changed by the superuser, but that is another ball game.

How the stepper motor works

How does it work?  The pole pieces are arranged in a triangle, with the ‘bottom’ pole pieces being the ends of the driver coils and the top pole piece being formed from the top end of the coils bending back to the rotor.  This means that when the coils are driven with opposite polarity, the north and south poles cancel out and the top pole piece is magnetically neutral.

Let’s assume the coils are energised such that the left-hand coil becomes a north pole and the right hand coil becomes a south pole. This requires the left-hand coil to be energised in direction 10, and the right-hand coil to be energised in the direction 01.  Magnetic force attracts the opposite poles of the rotor causing it to turn so that its south pole faces the north pole of the stator and its north pole faces the south pole of the stator.  The top pole is neutral at this point.

Pulse 2 makes both pole pieces into north poles, at the same time making the top pole piece into a South. This attracts the N of the rotor and repels the S of the rotor, causing the rotor to turn anticlockwise ¼ of a turn.   On Pulse 3, the left-hand coil now becomes an S and attracts the N of the rotor, whilst the S of the rotor is attracted to the N of coil 2.  On Pulse 4, both pole pieces are S, attracting the N of the rotor, whilst the top pole piece becomes an N and attracts the S of the rotor.  The next pulse is the same as Pulse 1 and we are back to the starting position.

It is clear that if the rotor is left in, say, position 3, and the pulsing sequence starts at 1, the rotor could turn either way to get to position 1. In either case, this would cause a positioning error.  To avoid this, the driver either needs to remember its position in the pulse sequence or it should always be driven a multiple of 4 pulses (one revolution) so that it is always at the appropriate starting position.

Using an H-bridge driver

The stepping sequence shown in the diagram is that of a typical H-bridge driver. The setting 1001 indicates the polarity of the two coils, with coil 1 being energised with polarity 10 and coil 2 by polarity 01 (i.e. the opposite polarity).  The direction of rotation will be reversed by changing the pulse sequence.  Thus, starting from position 1001, if the next step is 0101 (rather than 1010) the direction will be anticlockwise.  Some H-bridge drivers, such as The DRV8834 Stepper Motor Driver have a ‘direction’ pin that alters the pulse sequence accordingly.  They also remember the last step as long as they remain energised and ‘awake’.

By altering the relative current through the coils, it is possible to achieve coil positions intermediate to the main steps shown above.  The motor shown in this example works well at quarter steps but may not have as much starting torque.  Moreover, it is necessary to keep the coils energised in order to maintain an intermediate position.  The data sheet advises that the driver should be designed to accelerate and decelerate the pulse rate at the start and end of travel to ensure accurate stepping.

Clearly, it is worth using a H-bridge driver for non-trivial implementations.

Investigating an X27 Dial stepper motor

I use the X27 168 stepper motor for driving the barometer dials.  These are intended for driving the dials on a car dashboard, but I had no technical specification for them.  You can see from the photo that it is a bipolar motor – i.e. it has two coils each around a steel core which is extended to form curved pole pieces. The top of each core turns downwards under the cogs and come together to make a third pole piece, such that the pole pieces are at 120 degrees to each other.

You can see at the bottom of the photo that between the pole pieces there is a very small rotor, which consists of a small circular ceramic 2-pole magnet with very fine bearings and a small cog no more than a two or three millimetres in diameter.  The cog engages with another reducing gear which drives the output shaft via another reducing gear.  Each full rotation of the rotor (4 full steps) turns the output shaft by 2 degrees.  The result is that it takes 640 steps of the rotor to turn the output shaft through 320 degrees.  An end stop prevents it from continuing to rotate. The cogs are made of quite slippery plastic and whilst there is no obvious lubricant,  some PTFE type lubricant might have been applied during assembly.   The motor is held in a circular plastic housing about 30 mm diameter and about 10 mm thick.  The two halves are held by spring clips moulded into the housing. I will describe how it works in a separate post.

I have managed to find a Data Sheet for this motor!

The important parameters are that the motor coils have a resistance of about 255 ohms and are intended to be driven from a 5 volt source (maximum 9 v). This gives a current of about 20 mA.

The data sheet states that one full step creates half a revolution of the rotor, which is one degree of rotation of the output shaft.  (Maybe this depends on the definition of a full step, which doesn’t really affect this analysis.)

The datasheet goes on to say that each full step can be divided into 3 partial steps, so that a 360 degree rotation needs 1080 partial steps.

Importantly, it states that full steps can be carried out at 600Hz , i.e. 1.7 ms per step, resulting in a 600 degrees per second angular speed.  However, allowance must be made for acceleration and deceleration.  To avoid losing steps at the start, or overrunning at the end, the angular speed should be 200 degrees per second, although this depends on the inertial mass of the pointer.  So to achieve the maximum speed requires the pulse rate to be gradually increased and conversely on stopping.

I am need to achieve the most accurate rotation rather than the fastest, so a speed of 200 degrees/s is fine.  What step rate does this equate to?

I’ve determined that 4 pulses are needed from the stepper chip to rotate by 2 degrees, so I would need 400 pulses to rotate by 200 degrees.  This equates to a period of 1/400 = 2.5 ms.

Up till now I have been using a pulse duration of 3 ms with a pause of 3 ms between pulses (during which the coils are energised).  So essentially each pulse was 6 ms long. This was giving a noisy and jerky movement, and I observed that sometimes there was overrun.  Basically I was over-driving the motors.

So I have reduced the pulse length to 2.5 ms with no pause between pulses.  This is giving a smooth and quieter movement, without the tendency to overrun at the ends.

Due to the fairly soft materials that the cogs are made from, and given that my long pointer will have a fair amount of inertia, I’m thinking that the jerkiness was causing springiness and over-run.

The quicker but smoother movement is better matched to the dynamic response of the motor system.  The result looks promising!

 

Testing the not ENABLE pin

I had one GPIO pin unused (on the 26-pin version of the pi B), so I used this to route  a signal to the ¬Enable pin of the drivers.  I altered the code to wake the driver, enable the output, step the required number of times, disable the output and sleep the driver.

2-phase (bipolar) stepper motor showing very fine cogs

This ensures that the motors are de-energised before the logic sleeps, and it does definitely reduce the number of phantom pulses.  I can run the dials back and forth hundreds of times without losing place.  However, the large ‘weather’ hand sometimes appears to stumble.  This could be due to dirt on the cogs, as the teeth are extremely fine, as can be seen in the photo. The motor is about 25 mm (one inch) across.

But also, I need to sort out why the voltage on one of the coils seems lower.  Is there a problem?

The not ENABLE pin of the DRV8834

I’m continuing to investigate the ‘phantom’ pulses on the dials which cause them to get out of their expected position. To save pins on the Pi, I use one pin to ‘wake’ or ‘sleep’ the motor drivers.  This is sent to all the dials, so they all wake or sleep at once.

When the drivers are woken, the outputs are initially all low, and they energise when the step pin is pulsed.  Each time a step pin is pulsed, the outputs move to the next logic step and stay there until the step pin is pulsed again.

Any motor that is stepped thus has its coils energised and when the driver is slept the stepping logic is reset and any motor that was stepped will have its coils de-energised.  This can cause a brief pulse on the coils.

This is not what I want.  However, there is a  ¬Enable (¬ means not) pin that is held low (i.e. enabled) by a pull-down resistor.  The Pololu datasheet says you can ignore this pin.  But the 8834 datasheet explains that ¬Enable disables the output stage of the driver without resetting the logic.  In other words, it de-energises the motor coils, but the chip remembers the last step.  This would mean that all the outputs are de-energised before the phantom pulse caused by going to sleep and also get over all the problems of the motors being in an undefined state at the start of each stepping cycle.

Looking at my circuit layout, I see that pin 19 (GPIO 10) is the only GPIO pin unused, but could be used to enable or ¬enable the drivers.  Maybe this might stop the phantom pulses?

Investigating a DRV8834 Stepper Motor Driver

The Barometer uses small car dashboard stepper motors for driving the dials, but it has never been entirely satisfactory as the dials easily lose position.  This seems to be due to random movement, especially because they sometimes flip backwards a notch at the end of their motion as described here: Inaccurate stepping.  I am now trying to get to the bottom of this, using the oscilloscope I acquired for the purpose.

The steppers are bipolar, meaning they have two coils which need to be energised in a certain sequence.  For the reasons mentioned here: Thinking about the electronics I bought DRV8834 low-voltage stepper drivers to operate the dials.

With these drivers, you only need to set the direction and supply the pulses.  There is a pin to wake or sleep the drivers when not used, which is great because the barometer only changes when the weather forecast is updated and the dial hands will stay in place when not energised.

The drivers can be set to move in full steps and fractional steps.  However, fractional steps required the motor coils to be kept energised, so I was intending to use full steps.

Connecting the Oscilloscope

My oscilloscope has four input channels: in essence, each channel measures the voltage on its input, relative to ground.  In common with most electronics, my circuit has the negative rail grounded, but to ensure a good ground connection, I connected the negative rail of the circuit to the ground connection of the oscilloscope.  (Oscilloscopes have a very high input impedance, so without a good ground, the signal will can be obscured by mains ‘hum’ and RF pickup, giving a fuzzy display.)

I selected a particular stepper and connected Channels 1 and 2 to opposite ends of motor coil 1, and Channels 3 and 4 to opposite ends of motor coil 2.  Using a short Python routine, I sent ten 2 ms pulses to the motor.  The pulses are preceded by raising a wake signal to the driver and terminated by dropping the wake signal.

Two coils being pulsed

 

Two coils displayed

The above oscilloscope display shows a sequence of 10 pulses on motor coil 1 (ch1 = yellow, ch 2= blue) and motor coil 2 (ch 3 = Green, ch 4 = Red).  Using 1 to represent high and 0 to represent low, we can see:

1 0 0 1
1 0 1 0
0 1 1 0
0 1 0 1
1 0 0 1
1 0 1 0
0 1 1 0
0 1 0 1
1 0 0 1
1 0 1 0

Looking at this sequence both coils are always energised, but in a sequence that rotates:
coil 1 north, coil 2 south
coil 1 north, coil 2 north
coil 1 south, coil 2 north
coil 1 south, coil 2 south
repeat

After the last long pulse, there is a short but strong pulse on 2 and 4, equal to 0101.  I’m assuming this is generated by the ‘sleep’ pulse, as the motors are then de-energised.

The horizontal scale represents time, at 5 ms per division so each pulse lasts for 4 ms. I had assumed that the coils would only be energised for the time that the pulse pin was held high, followed by an un-energised pause, but this is not the case: the pulse pin is held high for 2 ms, then set low for the 2 ms pause before the next pulse, but the coils remain energised in their current state until the next pulse.  This makes sense where microsteps are obtained by partial energisation of the coils.

The final step in the sequence will depend on how many pulses were sent.  If it is not a multiple of four, the motor could end up in some random end state such that it might not be able to respond to the initial pulse, as I don’t suppose the chip remembers the last state it was in.  So it could lose as many as three pulses on each movement, which over a few days would certainly throw it out.  The answer would be to round the pulses to a multiple of four.

I am also concerned as to why the voltage on ch1 is only about 0.5 V and on ch 2 about 4 V – this means coil 1 is energised more strongly in one direction than the other – but this is something for later.

So now I have something to work on!

 

 

Raspberry Pi Enclosures

A change of subject today.  Raspberry Pi enclosures.  There are an awful lot of them about.  This is not a scientific review but describes my experience with a few that I have tried out.

Raspberry Pi B
Raspberry Pi B

The first one was the Pimoroni, made of  multi-layered, multi-coloured Perspex sections, held together with long nylon bolts at the four corners.  It was fine and I used it in my Barometer.  The only trouble is that you have to undo the bolts to gain access, which can be inconvenient, but they give you a groovy little ‘spanner’ to assist, and if you connect a ribbon cable, you’ll rarely need to do this.  So it’s great fun.  I fixed it to the Barometer casing by replacing the nylon bolts with brass ones, taking care to insulate the circuit board where the bolts passed through. It has plenty of ventilation.  Perhaps not the most convenient project enclosure and not the cheapest at around £11 +VAT.

Pink and white enclosure
Pink and white enclosure

The second one was the ‘Official Raspberry Pi’ raspberry pink and white groovy-shaped box. Around £5.50 +VAT from RS Components. It is easy to clip and unclip the lid, the sides and the inner cover, and to get access to the GPIO pins. It has soft plastic pads on the base, but with the Pi being so small and light, it won’t stay on your desk if there is any tension on any of the connecting leads.  There are no fixing holes. You’d need to take the lid off if ventilation was an issue.  A very pretty box but very much at the mercy of your connecting leads.

Raspberry box with covers removed
Raspberry box with covers removed
Clear plastic box
Clear plastic box

The third one was the DesignSpark  clear transparent case (available in other colours) also around £5.50+VAT from RS.  This has ventilation holes in the base and slot all round the sides of the case.  However, the lid is only held on by the friction fit of four small lugs.  Once you have taken the lid off a few times, you will need sticky tape or some other way to keep it on.  It is very easy to assemble and has fixing holes in the base. Also, you can easily see the indicator LEDs and the GPIO connections.  This has become my favourite for project work.

Clear box with Pi board fitted
Clear box with Pi board fitted

The fourth is an entirely different proposition. It is the DesignSpark ‘Quattro’ case which holds the Pi and a thin 2.5-inch HDD (or SDD) in a very presentable square black box. (Other colours are available.) This is intended for use as a media server and is a very neat solution, for only £8.99 +VAT from RS Components, which is inexpensive when you look at the cost of ordinary project boxes.

Prior to this, I’d intended to put the Pi in a sandwich box along with a USB hard disk, but I was put off by the work involved in making access holes for the HDMI and power leads and fixing everything firmly.  My other half complained that it looked too complicated and untidy to have on the TV stand, and I’d gone back to saving home videos onto USB flash drives.  They supply it with a ‘VESA’ mount which would allow you to fix it onto the back of a monitor to provide a nice all-in-one display unit.

DesignSpark Quattro Case
DesignSpark Quattro Case

This box makes it all much neater. You put the Pi circuit board in first, and then a bare-bones 2.5 inch HDD. The base then clips on firmly.  You can access the Pi’s GPIO pins and the camera and display connectors from above.  There are no apertures in the box specifically for these connectors, but they supply spacers which will create a slot between the lid and the sides if you need access or to add a circuit board or HAT.  Also, there is a small round aperture at the ‘front’ of the box and a slot behind it to hold the Pi’s camera, so you could use this as a webcam or even a ‘hidden’ camera.  However, next to the camera aperture there are two light guides for the Pi’s activity LEDs, so the Pi’s presence may not be secret.

The Quattro case with Pi board and Seagate Hard disk
The Quattro case with Pi board and Seagate Hard disk

The camera aperture is in a slot-in cover which can be removed to reach the SD card. The whole unit can be secured by screws from underneath (not supplied) to deter prying fingers or accidental disintegration.

Seagate Barracuda 1 TB disk
Seagate Barracuda 1 TB disk with USB connecting cable

I bought a Seagate Barracuda 1 TB 2.5 inch SATA HDD for storing the media. This disk requires a power supply of 1A at 5V which is supplied over the USB connector. I could have gone for a larger capacity, but this will be fine for my purposes.

The box does not have any means of connecting the HDD to the Pi.  I have bought a StarTech USB3S2AT3CB USB to SATA connecting cable for this.  Although this cable is very short, you have to coil it rather annoyingly round the outside of the box.

Logitech keyboard
Logitech keyboard

Of course, a media server needs some sort of user interface.  I bought a Logitec K400+ TV keyboard for this purpose.  It uses ordinary wireless communication, not Bluetooth.  I’ve had trouble with Bluetooth keyboards.  They seem to go to sleep after a period of inactivity, and when you press a key to pause the film, etc, there is no response.  If and when the keyboard and Pi start talking again, you have tapped so many keys so many times that either the program has crashed or done something equally annoying. I’ve also had trouble with pairing Bluetooth devices – some won’t pair at all. The wireless keyboard doesn’t seem to suffer from this, and it includes a trackpad for scrolling and selecting.

Installing the HDD
The ‘barebones’ Seagate HDD [type ST1000LM048] is not formatted when you get it and the Pi just did not find it. Rather than struggle with sorting it out on the Pi,  I plugged it into a USB3 port on my PC which simply showed a device called ASMT 2115 SCSI Disk Device.  The Seagate disk manager software refused to do anything because it could not detect a Seagate disk.

So I went to the Windows Run command and started the disk manager using the command run diskmgmt.msc.  This showed the Seagate drive but said it was uninitialized. Being careful not to select the wrong drive by mistake, I selected that drive and clicked initialize.  I assigned an arbitrary drive letter and gave it a volume name, SeagPiMedia.  Then I formatted it with NTFS.  This file system is readable on both the PC and the Pi, which means I can put files onto the disk using either machine.

After putting some video files on it, I plugged it back into the Pi.  It was then visible in /media/pi/SeagPiMedia. Brilliant!  I put some video files on it and they play beautifully using OMXPlayer and Kodi.  The keyboard works very well too.  Maybe we can view our my old videos again.

Update on the Barometer

I mentioned in an earlier post that I wondered whether the BBC weather forecast RSS feed might disappear once they had a new forecast provider.  Well, at the beginning of the week, the barometer stopped working – it locked up.  Eventually I used Remote Desktop to open it and saw that it was complaining that ‘null’ wasn’t a valid temperature. I looked at the actual feed and realised that the temperatures were all set to ‘null’ and then I realised that the dates were wrong.  A bit of Googling quickly revealed the new address for the feed and luckily it is still in the same format as previously.  So I was soon up and running again.

I still have to correct a few small glitches – maybe there will be some time over this weekend.

New BBC weather forecast

Users of the BBC weather forecast will know that they have now gone over to a new forecast provider with new, and in my view greatly improved, graphics.  Thankfully they don’t seem to have changed the format of the 3-day forecast because the barometer still works.

I mentioned some while ago that I was going to try an official Raspberry Pi 2.5 amp power supply unit in the expectation that it would transmit less mains interference, but that its lead was too short. Eventually I got around to soldering in an extra length of lead and fitting the unit.  Sadly, it has not improved the performance at all.  Apparently these units have a current limiter – if you try to draw more than 2.5 amps, the output voltage automatically reduces.  I can’t imagine that the driver circuitry uses anything like that current – the stepper motors only use about 30 mA and they run one at a time.

As I have said before, I don’t have an oscilloscope but I suspect there are still parasitic pulses somewhere. I think some additional decoupling capacitors are still needed.  As soon as my other commitments ease off, I will try to apply the finishing touches.

I’m wondering what project to try next – I think a moonrise and moonset and moonphase clock would be nice. I’ve been reading about the difficulty of calculating these and I’ve even found Fortran code for an algorithm.  It’s not as simple as I thought, but that’s the whole point, I guess.

Weather Forecast?

We all know not to put too much trust into the weather forecast, but now my ‘barometer’ is showing the BBC forecast quite reliably, it is leading me to wonder just what the forecast means. The three-day forecast from the BBC server is updated about four times a day, and has forecasts for today, tomorrow and the next day.

Ever since  BBC weather forecaster Michael Fish famously announced that ‘there will be no hurricane tonight’ just before the worst storm in living memory, the BBC have become more cautious, seeming to revel in making dramatic announcements about the weather.

This week we have been in a period of changeable weather, with dramatic pictures of snow, ice, strong winds and traffic hazards in the north, but cold, windy days with sunshine and showers in the south.

Last night, the forecast for Epsom, just south of London, for ‘tonight’ was ‘light cloud’.  But I was woken by heavy rain beating on the windows. So I looked at the hourly breakdown, which correctly showed strong winds and heavy rain.  This meant that the forecast was internally inconsistent, and leads me to wonder what the forecast for ‘today’ or ‘tonight’ actually represents. They don’t seem to say. It has been essentially wrong all week, showing ‘light cloud’ when it was either raining or sunny. The wind speed and direction have mostly been correct, and I don’t have any means of checking the pressure or humidity, but this has seemed to be fairly steady.

I have always thought that Epsom has a bit of a ‘micro-climate’ which explains the errors in weather forecasts.   It is at the foot of the chalky ‘North Downs’ [this always confuses me because the North Downs are south of London: the reason being that the South Downs are on the south coast (think of Beachy Head and the White Cliffs of Dover).]  The North Downs create a rain shadow to weather approaching from the south and west, whilst weather coming from the north will have lost much of its rain over the Dunstable Downs to the north of London and must also be affected by the vast London conurbation.  As a result, Epsom has a dry climate and is often regarded as a very healthy place to live.  It used to be a spa town – the spring that gave Epsom Salts is still there but sadly surrounded by a large housing estate.

Nevertheless, as a display device, I think I can claim that the Barometer is a success.