Translate

Saturday, 30 August 2014

Arduino Astronomical Clock (or Arduino Pond Pump Controller!)

****** A lot of people land on this page. Welcome. There are a few updates on this project (the last being here.) so it's worth checking through the blog for updates. Thanks ******




It's been a great summer here in the UK. I built myself something I'd always wanted. A bit of a water feature in my garden. The sound of trickling water whilst relaxing in the garden ... ahhhh !

Well, I didn't like the thought of the pump running all night, wasting all that precious energy, so a solution was required....

The usual thoughts of a photodiode (even an led works as a photodiode, try it!) or LDR and comparator were soon dispelled, as I'd done such things as a kid, and it's a horrible thing to set up. Clouds causing shadows, neighbours outside lights switching it on etc etc ... no , we need something a little more sophisticated.

Now, a guy called Paul had done the same thing, but backwards (switching something on at dusk, and off at dawn), and his website here shows a rather nice unit built using recycled bits and pieces. "Just the job".. except I need more coding experience, so I blatantly copy some of Paul's thoughts and the use of the Timelord library.

Although I love the idea of recycling the display, I just don't have anything to recycle at present, other than the usual 2 x 16 LCD I've removed from a DAB radio, and a nice rotary encoder, so we'll go with those.

Now, keeping time....

This is a DS1307 module, purchased at very little expense (but a bit of a wait) on eBay. It's a fully fledged real-time clock, which sends it's data via an I2C interface. Just the job. On the rear of this fella is a button cell holder. Just beware. Order yours with the battery. You can get a version which takes an ordinary 2023 Lithium coin cell, or an LIR2023 Lithium-ion coin cell, which charges off the supplied 3.3 or 5 volts. Don't try and charge an ordinary 2023 cell. It won't be pretty.


OK, so that's our time keeping sorted.

So, time to conjure up some hardware....




My 5v supply is a little buck converter, which is driven from the 24VAC from the pond transformer. The Arduino (Nano in this example) is mounted on a bit of perf board, along with a relay module and the DS1307 RTC board.
















Now copy the code into your IDE, and alter the LATITUDE and LONGITUDE constants to your position on the planet. Google maps comes in handy here, or just pop outside with a GPS.
Upload the code (below) and your display should show something like this. American users may wish to note the date is in the UK standard (DD/MM/YYYY), you can, of course, alter the code to suit your own preferred format.

Now, if that's not UTC (and unless you're in the UK in winter, or your PC is set to UTC, it won't be) press and hold the button for 5 seconds. When you release the button the display will show "Set Year". You can alter this using the rotary encoder. If the encoder works back to front, reverse the wires to pins D2 & D3 on the Arduino board. Pressing the button moves the menu on to set Month. Pressing again, set the day, then hour and then minute. Once the minute is set the RTC is set, and the clock display will revert after 1 second. Excellent. The clock is now set and running.

Pressing and releasing the button once will display the current calculated sun rise and sunset time.

If you wait the display will revert back to the clock after a few seconds.

Pressing again whilst the sunrise and sunset times are display will allow you to alter the mode of the clock. Auto switches the output on when the sun rises, and off when it sets.
On switches the output on permanently. Finally off leaves the output off.


Finally, mount the whole shooting match on the wall, make it neat and go for a pint or two to celebrate!















Here's the code:

// Dawn & Dusk controller.
// 16th August 2014.
// (C) A.G.Doswell 2014
//
// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
//
// Designed to control a relay connected to pin A3. Pin goes low during daylight hours and high during night. Relay uses active low, so is
// "On" during the day. This is connected to the fountain pump in my garden.
//
// Time is set using a rotary encoder with integral push button. The Encoder is connected to interrupt pins D2 & D3 (and GND), 
// and the push button to pin analogue 0 (and GND)
// The RTC is connections are: Analogue pin 4 to SDA. Connect analogue pin 5 to SCL.
// A 2 x 16 LCD display is connected as follows (NOTE. This is NOT conventional, as interrupt pins are required for the encoder)
//  Arduino LCD  
//  D4      DB7
//  D5      DB6
//  D6      DB5
//  D7      DB4
//  D12     RS
//  D13     E
//
// Use: Pressing and holding the button will enter the clock set mode (on release of the button). Clock is set using the rotary encoder. 
// The clock must be set to UTC.
// Pressing and releasing the button quickly will display the current sun rise and sun set times. Pressing the button again will enter the mode select menu. 
// Modes are AUTO: On when the sun rises, off when it sets.
//           ON: Permanently ON
//           OFF: Permanently OFF (Who'd have guessed it?)
//
// Change the LATTITUDE and LONGITUDE constant to your location.

#include <Wire.h>
#include "RTClib.h" // from https://github.com/adafruit/RTClib
#include <LiquidCrystal.h>
#include <Encoder.h> // from http://www.pjrc.com/teensy/td_libs_Encoder.html
#include <TimeLord.h> // from http://swfltek.com/arduino/timelord.html. When adding it to your IDE, rename the file, removing the "-depreciated" 

RTC_DS1307 RTC; // Tells the RTC library that we're using a DS1307 RTC
Encoder knob(2, 3); //encoder connected to pins 2 and 3 (and ground)
LiquidCrystal lcd(12, 13, 7, 6, 5, 4); // I used an odd pin combination because I need pin 2 and 3 for the interrupts.
//the variables provide the holding values for the set clock routine
int setyeartemp; 
int setmonthtemp;
int setdaytemp;
int sethourstemp;
int setminstemp;
int setsecs = 0;
int maxday; // maximum number of days in the given month
int TimeMins; // number of seconds since midnight
int TimerMode = 2; //mode 0=Off 1=On 2=Auto
int TimeOut = 10;
int TimeOutCounter;

// These variables are for the push button routine
int buttonstate = 0; //flag to see if the button has been pressed, used internal on the subroutine only
int pushlengthset = 3000; // value for a long push in mS
int pushlength = pushlengthset; // set default pushlength
int pushstart = 0;// sets default push value for the button going low
int pushstop = 0;// sets the default value for when the button goes back high

int knobval; // value for the rotation of the knob
boolean buttonflag = false; // default value for the button flag


const int TIMEZONE = 0; //UTC
const float LATITUDE = 51.89, LONGITUDE = -2.04; // set YOUR position here 
int Sunrise, Sunset; //sunrise and sunset expressed as minute of day (0-1439)
TimeLord myLord; // TimeLord Object, Global variable
byte sunTime[]  = {0, 0, 0, 1, 1, 13}; // 17 Oct 2013
int SunriseHour, SunriseMin, SunsetHour, SunsetMin; //Variables used to make a decent display of our sunset and sunrise time.

void setup () {
    //Serial.begin(57600); //start debug serial interface
    Wire.begin(); //start I2C interface
    RTC.begin(); //start RTC interface
    lcd.begin(16,2); //Start LCD (defined as 16 x 2 characters)
    lcd.clear(); 
    pinMode(A0,INPUT);//push button on encoder connected to A0 (and GND)
    digitalWrite(A0,HIGH); //Pull A0 high
    pinMode(A3,OUTPUT); //Relay connected to A3
    digitalWrite (A3, HIGH); //sets relay off (default condition)
    
    //Checks to see if the RTC is runnning, and if not, sets the time to the time this sketch was compiled.
    if (! RTC.isrunning()) {
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }
 
 
    //Timelord initialisation
    myLord.TimeZone(TIMEZONE * 60);
    myLord.Position(LATITUDE, LONGITUDE);
    CalcSun ();
}
           

void loop () {
  
    DateTime now = RTC.now(); //get time from RTC
    //Display current time
    lcd.setCursor (0,0);
    lcd.print(now.day(), DEC);
    lcd.print('/');
    lcd.print(now.month());
    lcd.print('/');
    lcd.print(now.year(), DEC);
    lcd.print("    ");
    lcd.setCursor (0,1);
    lcd.print(now.hour(), DEC);
    lcd.print(':');
    if (now.minute() <10) 
      {
        lcd.print("0");
      }
    lcd.print(now.minute(), DEC);
    lcd.print(':');
    if (now.second() <10) 
      {
        lcd.print("0");
      }
    lcd.print(now.second());
    lcd.print("     ");
    
    //current time in minutes since midnight (used to check against sunrise/sunset easily)
    TimeMins = (now.hour() * 60) + now.minute();
    
    // Calculate sun times once a day at a minute past midnight
    if (TimeMins == 1) {
      CalcSun ();
    }
    if (TimerMode ==2) {
      if (TimeMins >= Sunrise && TimeMins <=Sunset-1) { //If it's after sunrise and before sunset, switch our relay on
          digitalWrite (A3, LOW);
          lcd.setCursor (13,1);
          lcd.print ("On ");
        }
        else {  //otherwise switch it off
          digitalWrite (A3, HIGH);
          lcd.setCursor (13,1);
          lcd.print ("Off");
        }
      }
       if (TimerMode ==0) {
         digitalWrite (A3, HIGH);
         lcd.setCursor (13,1);
         lcd.print ("Off");
       }
     
       if (TimerMode ==1) {
         digitalWrite (A3, LOW);
         lcd.setCursor (13,1);
         lcd.print ("On ");
       }
    
    pushlength = pushlengthset;
    pushlength = getpushlength ();
    delay (10);
    
    if (pushlength <pushlengthset) {
     
      ShortPush ();   
    }
    
       
       //This runs the setclock routine if the knob is pushed for a long time
       if (pushlength >pushlengthset) {
         lcd.clear();
         DateTime now = RTC.now();
         setyeartemp=now.year(),DEC;
         setmonthtemp=now.month(),DEC;
         setdaytemp=now.day(),DEC;
         sethourstemp=now.hour(),DEC;
         setminstemp=now.minute(),DEC;
         setclock();
         pushlength = pushlengthset;
       };
}

//sets the clock
void setclock (){
   setyear ();
   lcd.clear ();
   setmonth ();
   lcd.clear ();
   setday ();
   lcd.clear ();
   sethours ();
   lcd.clear ();
   setmins ();
   lcd.clear();
   
   RTC.adjust(DateTime(setyeartemp,setmonthtemp,setdaytemp,sethourstemp,setminstemp,setsecs));
   CalcSun ();
   delay (1000);
   
}

// subroutine to return the length of the button push.
int getpushlength () {
  buttonstate = digitalRead(A0);  
       if(buttonstate == LOW && buttonflag==false) {     
              pushstart = millis();
              buttonflag = true;
          };
          
       if (buttonstate == HIGH && buttonflag==true) {
         pushstop = millis ();
         pushlength = pushstop - pushstart;
         buttonflag = false;
       };
       return pushlength;
}
// The following subroutines set the individual clock parameters
int setyear () {
   lcd.setCursor (0,0);
    lcd.print ("Set Year");
    pushlength = pushlengthset;
    pushlength = getpushlength ();
    if (pushlength != pushlengthset) {
      return setyeartemp;
    }

    lcd.setCursor (0,1);
    knob.write(0);
    delay (50);
    knobval=knob.read();
    if (knobval < -1) { //bit of software de-bounce
      knobval = -1;
    }
    if (knobval > 1) {
      knobval = 1;
    }
    setyeartemp=setyeartemp + knobval;
    if (setyeartemp < 2014) { //Year can't be older than currently, it's not a time machine.
      setyeartemp = 2014;
    }
    lcd.print (setyeartemp);
    lcd.print("  "); 
    setyear();
}
  
int setmonth () {

   lcd.setCursor (0,0);
    lcd.print ("Set Month");
    pushlength = pushlengthset;
    pushlength = getpushlength ();
    if (pushlength != pushlengthset) {
      return setmonthtemp;
    }

    lcd.setCursor (0,1);
    knob.write(0);
    delay (50);
    knobval=knob.read();
    if (knobval < -1) {
      knobval = -1;
    }
    if (knobval > 1) {
      knobval = 1;
    }
    setmonthtemp=setmonthtemp + knobval;
    if (setmonthtemp < 1) {// month must be between 1 and 12
      setmonthtemp = 1;
    }
    if (setmonthtemp > 12) {
      setmonthtemp=12;
    }
    lcd.print (setmonthtemp);
    lcd.print("  "); 
    setmonth();
}

int setday () {
  if (setmonthtemp == 4 || setmonthtemp == 5 || setmonthtemp == 9 || setmonthtemp == 11) { //30 days hath September, April June and November
    maxday = 30;
  }
  else {
  maxday = 31; //... all the others have 31
  }
  if (setmonthtemp ==2 && setyeartemp % 4 ==0) { //... Except February alone, and that has 28 days clear, and 29 in a leap year.
    maxday = 29;
  }
  if (setmonthtemp ==2 && setyeartemp % 4 !=0) {
    maxday = 28;
  }
  
   lcd.setCursor (0,0);
    lcd.print ("Set Day");
    pushlength = pushlengthset;
    pushlength = getpushlength ();
    if (pushlength != pushlengthset) {
      return setdaytemp;
    }

    lcd.setCursor (0,1);
    knob.write(0);
    delay (50);
    knobval=knob.read();
    if (knobval < -1) {
      knobval = -1;
    }
    if (knobval > 1) {
      knobval = 1;
    }
    setdaytemp=setdaytemp+ knobval;
    if (setdaytemp < 1) {
      setdaytemp = 1;
    }
    if (setdaytemp > maxday) {
      setdaytemp = maxday;
    }
    lcd.print (setdaytemp);
    lcd.print("  "); 
    setday();
}

int sethours () {
    lcd.setCursor (0,0);
    lcd.print ("Set Hours");
    pushlength = pushlengthset;
    pushlength = getpushlength ();
    if (pushlength != pushlengthset) {
      return sethourstemp;
    }

    lcd.setCursor (0,1);
    knob.write(0);
    delay (50);
    knobval=knob.read();
    if (knobval < -1) {
      knobval = -1;
    }
    if (knobval > 1) {
      knobval = 1;
    }
    sethourstemp=sethourstemp + knobval;
    if (sethourstemp < 1) {
      sethourstemp = 1;
    }
    if (sethourstemp > 23) {
      sethourstemp=23;
    }
    lcd.print (sethourstemp);
    lcd.print("  "); 
    sethours();
}

int setmins () {

   lcd.setCursor (0,0);
    lcd.print ("Set Mins");
    pushlength = pushlengthset;
    pushlength = getpushlength ();
    if (pushlength != pushlengthset) {
      return setminstemp;
    }

    lcd.setCursor (0,1);
    knob.write(0);
    delay (50);
    knobval=knob.read();
    if (knobval < -1) {
      knobval = -1;
    }
    if (knobval > 1) {
      knobval = 1;
    }
    setminstemp=setminstemp + knobval;
    if (setminstemp < 0) {
      setminstemp = 0;
    }
    if (setminstemp > 59) {
      setminstemp=59;
    }
    lcd.print (setminstemp);
    lcd.print("  "); 
    setmins();
}

int setmode () { //Sets the mode of the timer. Auto, On or Off

    lcd.setCursor (0,0);
    lcd.print ("Set Mode");
    pushlength = pushlengthset;
    pushlength = getpushlength ();
    if (pushlength != pushlengthset) {
      return TimerMode;
    }

    lcd.setCursor (0,1);
    knob.write(0);
    delay (50);
    knobval=knob.read();
    if (knobval < -1) {
      knobval = -1;
    }
    if (knobval > 1) {
      knobval = 1;
    }
    TimerMode=TimerMode + knobval;
    if (TimerMode < 0) {
      TimerMode = 0;
    }
    if (TimerMode > 2) {
      TimerMode=2;
    }
    if (TimerMode == 0) {
    lcd.print("Off");
    lcd.print("  "); 
    }
    if (TimerMode == 1) {
    lcd.print("On");
    lcd.print("  "); 
    }
    if (TimerMode == 2) {
    lcd.print("Auto");
    lcd.print("  "); 
    }
    setmode ();
}

int CalcSun () { //Calculates the Sunrise and Sunset times
    DateTime now = RTC.now();
    sunTime[3] = now.day(); // Give Timelord the current date
    sunTime[4] = now.month();
    sunTime[5] = now.year();
    myLord.SunRise(sunTime); // Computes Sun Rise.
    Sunrise = sunTime[2] * 60 + sunTime[1]; // Sunrise returned in minutes past midnight
    SunriseHour = sunTime[2];
    SunriseMin = sunTime [1];
    sunTime[3] = now.day(); // Uses the Time library to give Timelord the current date
    sunTime[4] = now.month();
    sunTime[5] = now.year();
    myLord.SunSet(sunTime); // Computes Sun Set.
    Sunset = sunTime[2] * 60 + sunTime[1]; // Sunset returned in minutes past midnight
    SunsetHour = sunTime[2];
    SunsetMin = sunTime [1];
}

void ShortPush () {
  //This displays the calculated sunrise and sunset times when the knob is pushed for a short time.
for (long Counter = 0; Counter < 604 ; Counter ++) { //returns to the main loop if it's been run 604 times 
                                                     //(don't ask me why I've set 604,it seemed like a good number)
  lcd.setCursor (0,0);
  lcd.print ("Sunrise ");
  lcd.print (SunriseHour);
  lcd.print (":");
  if (SunriseMin <10) 
     {
     lcd.print("0");
     }
  lcd.print (SunriseMin);
  lcd.setCursor (0,1);
  lcd.print ("Sunset ");
  lcd.print (SunsetHour);
  lcd.print (":"); 
    if (SunsetMin <10) 
     {
     lcd.print("0");
     }
  lcd.print (SunsetMin);        

    
  //If the knob is pushed again, enter the mode set menu
  pushlength = pushlengthset;
  pushlength = getpushlength ();
  if (pushlength != pushlengthset) {
    lcd.clear ();
    TimerMode = setmode ();

  }
  
}

}
  
 

Thursday, 14 August 2014

Remote control solutions.

Been after a reliable replacement computer remote control solution ever since Logmein started charging. I don't use it enough or professionally, so couldn't justify coughing up for it.

A work collegue showed me the offering from TeamViewer. (http://www.teamviewer.com/) and it's just the job. File transfer, Apple, Windows, Linux & Android.

Nice....

Sunday, 10 August 2014

Dehumidifer datalogging...

<Deep voice over> Just when you thought it was safe to go into the attic</Deep voice over>

 Just when you thought the project was over (and it is really!) someone comes along and puts an idea in your head... "Hey, Andy, Why don't you log the data, and make some nice graphs" ... and, in reality, why would I want to .... because

a) I'm erring on the side of geeky

and

b) Because I can...

So, what's needed...

A scrappy old Windows box ... yes, this is just the ticket , 500 MB of RAM, 900MHz processor, 100MB HDD ... more than enough for the job.

A copy of Gobetwino, available here http://mikmo.dk/gobetwino.html

Another arduino board, another receiver and some code. (I suppose you could use your exisiting display, and just add the Serial.print bits to that code if you wished. Mine's all nicely boxed up, so it had to be stand alone)

// Receiver Sketch for Dehumidifier controller project
// Written by A.G.Doswell 08 Aug 2014
// Receiver connected to pin 9


#include <VirtualWire.h>
#include <VirtualWire_Config.h>

int TX_ID =10;
int Temp;
int Humidity;
int Dew;
boolean Output;
char buffer[5];
int led = 13;


void setup() {
              pinMode(led, OUTPUT);   
              //Comms set up
              Serial.begin(9600);
              // Virtualwire setup
              vw_set_tx_pin(10); // Even though it's not used, we'll define it so the default doesn't interfere with the LCD library.
              vw_set_rx_pin(9); // RX pin set to pin 9
              vw_setup(300); //sets virtualwire for a tx rate of 300 bits per second, nice and slow! 
              vw_rx_start();     
              }  
void loop()
{
typedef struct rxRemoteData //Defines the received data, this is the same as the TX struct
{
int    TX_ID; 
int    Temp;   
int    Humidity;
int    Dew;
boolean Output;

};

struct rxRemoteData receivedData;
uint8_t rcvdSize = sizeof(receivedData);

if (vw_get_message((uint8_t *)&receivedData, &rcvdSize)) 
{
  if (receivedData.TX_ID == 10)     { //Only if the TX_ID=10 do we process the data.
    int TX_ID = receivedData.TX_ID;
    int Temp = receivedData.Temp;
    int Humidity = receivedData.Humidity;
    int Dew = receivedData.Dew;
    boolean Output = receivedData.Output;
    digitalWrite(led, HIGH);
        
      // writes the received data to the serial interface
      
      Serial.print("#S|DATA|[");
      Serial.print(itoa((Humidity), buffer, 10));
      Serial.print(";");
      Serial.print(itoa((Temp), buffer, 10));
      Serial.print(";");
      Serial.print(itoa((Dew), buffer, 10));
      Serial.println("]#");
      digitalWrite(led, LOW);
 
      } 

  }
}

// End of file


So there it is. Load that into your favorite arduino, and connect a receiver to pin 9.
Now we need to tell Gobetwino what to do when it sees data from the com port. Firstly, quit the Arduino IDE. The two can't be running at the same time, or Gobetwino can't access the serial port the arduino is chatting on.

Firstly click on Commands.


Then click the New Command button. Using the drop down box , select LGFIL (Log data to file). Give it the Command name DATA (must be in capitals to match our Arduino data). Now create a blank data.txt file somewhere, using Windows explorer, just right click on a directory, click new and Text document. Name it data.txt. I chose the root of C: here for ease, but it can be anywhere....



Now back to Gobetwino. Click on the browse button, and point it to our freshly created data.txt file.


Check the Time stamp box. 

Click on save, and click on settings. Now click the serial port tab, and select the serial port our Arduino is communicating on. This is the same port the Arduino IDE was using.

Now every time the Arduino receives data from our transmitter, it will blink it's LED breifly, and send the data to Gobetwino, which will add a time stamp, and save it dutifully to the data.txt file.

You should end up (after a while) with a txt file looking a bit like this....

08/08/2014 16:13:15;28;36;14
08/08/2014 16:13:36;29;38;16
08/08/2014 16:13:58;29;38;16
08/08/2014 16:14:19;28;36;14
08/08/2014 16:14:40;28;36;14
08/08/2014 16:15:01;29;38;16
08/08/2014 16:15:22;28;36;14
08/08/2014 16:15:43;29;38;16
08/08/2014 16:16:04;29;38;16
08/08/2014 16:16:26;29;38;16
08/08/2014 16:16:47;29;38;16
08/08/2014 16:17:08;29;38;16
08/08/2014 16:17:29;29;38;16
08/08/2014 16:17:50;29;38;16
08/08/2014 16:18:11;28;36;14
08/08/2014 16:18:33;29;38;16
08/08/2014 16:18:54;29;38;16
08/08/2014 16:19:15;29;38;16
08/08/2014 16:19:36;29;38;16
08/08/2014 16:19:57;29;38;16
08/08/2014 16:20:18;29;38;16
08/08/2014 16:20:39;29;38;16
08/08/2014 16:21:01;28;36;14
08/08/2014 16:21:22;28;36;14
08/08/2014 16:21:43;28;36;14
08/08/2014 16:22:04;29;37;15


Now if we make a copy of the file, and change the extension to .csv (if windows worries about this making our file unusable, just carry on regardless!) It will then open in the spreadsheet programme of your choice (I choose OpenOffice), and with a little charting, we can create our graph...


Yes well, that's all very nice 'an 'all.... but wouldn't it be nice if the data was sent to me?

I'm not going to go into this in detail... as it took me hours to get it to work, and I'm still not really sure how I got it all to work... but there's a very useful piece of software called Sendemail available here: http://caspian.dotconf.net/menu/Software/SendEmail/ that I configured using the usual Windows task scheduler to copy the file, email me the copy, and then install a new blank in it's place... and it works a treat!

That's it for this project. It REALLY is... 



Saturday, 9 August 2014

GEC 2028

Been after one of these old girls for a while now. Picture the scene. It's 1967. Colour TV has just started in the UK. Sets are an arm and a leg. This was the cheapest colour TV available at he launch of the Colour TV service (BBC 2 only at the time) as it used a Mullard 19" tube (A49-11X) , whereas the competition all used the bigger 25" A63-11X.

It's a dual standard 405 line/ 625 line set, and much in keeping with bodges done once everything was in colour this one has had it's system switch permanently set to 625 lines. This I had to reverse to restore the set to full operation.


The set arrives....








Off with the back... system switch lever missing...








One of the RGB output valves is down to air (the getter has turned white). It's a PCL 84, but no worry, I have a NOS "Pinnacle" branded one to fit.







Then, my heart sinks.... I'm just about to check the condition of the CRT, when I spot a crack all the way round the CRT neck....





The CRT is made from purest unobtainium. I'm gutted, but hook up the B&K CRT analyser to check it , but I don't hold out any hope....






As usual with a CRT that's been standing for years, there's almost no emission, but the CRT heaters glow about the right colour when connected to the tester, which is good, as if the tube was down to air, they would burn bright. Slowly, oh so very slowly, emission starts to occur, and after a few hours, the CRT tester shows we have a very good tube. I disconnect the main reservoir capacitors and leave them to reform on the "MK87B Dreadnaught Capacitor reformer"

I'm still very nervous of that crack in the CRT, but gently apply some mains to the set (after replacing the reformed electrolytics). There's a smell of warm dust from the dropper resistor as it wakes from it's slumber... The valve heaters light .... There's a hiss from the speaker ... but no life from the line output stage. Easy fix, the anode wire has broken off the top cap of the PL509 line output valve. A quick dab with a hot iron, and I start the procedure again...

This time, there's some life from the line output stage, followed by some fizzing, popping and crackling from the line output "cage". Not Good. Mains quickly removed. The line output cage houses the line output transformer and a semi-conductor EHT "Tripler" or multiplier. The EHT tripler creates the 25KV used to drive the final anode of the tube, and in this set it also feeds a VDR dividing network to derive the 7KV focus voltage.

I ran the set again in the dark, with the top off the cage, and it was obvious the tripler was arcing to earth where the EHT lead exited the case, so I removed the tripler and the focus VDR.






I removed the damaged insulation, and soldered a new piece of EHT lead to the tripler. I then filled the join with epoxy resin to insulate it. 25KV is difficult to keep insulated, so I also expoxy bonded two pieces of perspex to the tripler case to prevent any corona or arcing.




Once the tripler was installed again, it was time to apply mains again....







.... and after a few minutes, a bit of fiddling, a test card was displayed, low in height and no frame lock at all! Checking around the frame stage revealed 7 resistors well out of spec, and two suspect electrolytic capacitors. Once these were changed....





... the set resolved a very reasonable picture.









Manually operating the standards switch and feeding in a VHF 405 line signal in, the set displayed nothing but interference. No amount of trying could get the tuner to move. It was seized solid. Removal is not an easy task, and I was still wary of that crack in the CRT neck...




The screw threads which move the slugs in and out of the tuning inductors were seized solid. Some cleaning with IPA to remove the hardened grease, and application of petroleum jelly soon freed everything up and restored the operation of the VHF tuner.

Once the tuner was refitted, I could tune in the output from my 405 line test card generator, but line lock was difficult, and getting a lock on 405, threw out the line lock on 625.

After much head scratching , and checking of quite a few components in the 405 section of the line stage, I find the fault .... in the 625 section! It's obvious that the set developed a line sync fault, and was fudged to work on 625 only (what's the betting that's when the standards switch lever was removed). The 625 section of the line oscillator was loading down the 405 section. It was a faulty polyester film capacitor, very much outside of tolerance.

EHT was adjusted to 25KV on both standards, and I set about setting up the convergence...







 ... and snapped the blue lateral magnet in the process ...








.... which was duly repaired with some very nice orange heatshrink sleeving....








... and allowing a very nicely converged colour picture.








I fabricated a standard switch lever (which is operated by a cam on the VHF tuner. It operates the lever when switched to the VHF position). A tag soldered on to a piece of wire coathanger at the top....





 ... and a catch at the bottom to hold it in place.









 ... allowing us to switch between 405 lines monochrome...
... and glorious colour 625 lines at the turn of a knob!
video

Flicker here is caused by the difference in frame rate of the camera and the TV screen. It's not evident in real life!

Post-scipt....

THE CRACK!
After some research (mostly on http://www.forum.radios-tv.co.uk ) , and a chat with Peter from http://www.notobsolete.co.uk , it turns out that the crack is just a weld in the neck of the CRT. This was done by the original manufacturers of the tube (Mullard) when producing a factory re-gunned tube. Now I can relax!