Friday 9 January 2015

Running MPLab IDE from MAC Book Pro

Did a bit of a Google on the subject of this post and found that various things don't quite work on the MAC. Yes you can get MPLabX for the MAC but MPLabX doesn't support PicKit2 (my preferred mode of operation) - all my dev up to now has been on my Windows7 laptop, where I have MPLab8 & various C compilers. The problem is that in my electronics lab I only have a MAC, well actually this isn't completely true as I have a Windows desktop and several Linux servers, but the Mac is right next on my electronics work bench and I have put a monitor on the wall above - so I have the motivation to make my MacBook run MpLab8, which means running windows7 on it.


So after much faffing around I decided to make my 2007 MacBookPro run Windows using Boot Camp. Upon initial investigation this seems very straight forward, well it is if you have a modern MacBook, which mine isn't (although I did put a 1T hybrid drive in it which makes it very quick).


The steps are as follows:


1. Run boot camp installer, this will ask you to make a BOOTCAMP partition, I made mine 153G, for no real reason, other than the minimum of 37G seems very piddle.


2. Get the original Windows 7 install disk and let Boot Camp boot from it to do an install.


This is where the fun begins.... It starts to appear to boot, then shows the text:


Select CD-ROM Boot Type...
1:
2:


Then you can go no further, you cannot select 1 or 2 or anything.


To get round this then you need to make a new Windows 7 boot disk - this is very straight forward, but does require a few additional tools.


Firstly go to:
http://www.iruberleet.org/2011/10/12/fixing-select-cd-rom-boot-type-when-installing-64bit-windows/


Create 2 directories on the root of your C: drive called windows7contents and newwindows7dvd
then follow the instructions at the top of the article. This will create you an ISO, but don't go rushing off to burn this image to a DVD - it won't boot in the MAC.


Now go over to http://www.winiso.com/download.html and download the free version of the tool - at time of writing this was 5.3 - and install (I was actually able to install version 6, which seemed to be included in the download - I'm sure any version will work)


Using WinISO create an img file: From the Bootable menu select "Extract Image", select the ISO then save this in the same directory as the ISO itself.


Then from the Bootable menu -> "Select Boot Image" and select the img file created in the previous step.


Then put a blank DVD in your DVD r/w drive and click on Burn.


Then you can proceed to install windows.


(This is all described well here, http://www.simplehelp.net/2009/01/15/using-boot-camp-to-install-windows-7-on-your-mac-the-complete-walkthrough/ but if you have an old Mac like me then you are stuck with Boot Camp 3.)

PIC to TC35 comms issues

Ahhhhhhhhhhhhh, ahhhhhhhhh, noooooooo etc.

Right I have the comms OK from PC to TC35, I can sent comms ok from PIC to PC. So why oh why cant I send the comms from the PIC to the TC353....it's the same commands!!

This diagram explains the problem....

I can't figure out why the MAX232 on the TC35 side won't even register that it is receiving anything. When the PC is sending AT commands to the TC35 RS232 the TX & Rx lights blink. But when the PIC is trying to do the same there is not acknowledgement of anything being received. Eh!!

Thursday 8 January 2015

Can now receive calls!!

I have been messing about with the TC35 GMS modem module and trying to get calls received.

According to the DOCs the word "RING" should be received when a call is received. Indeed I have experienced this when I was using the Nokia in the older version of Retro-Mobile.

I have literally spent hours trying to get a call received via the build in 9-D RS232 comms socket connected to my USB-COM port.

I was just about to order a new one on ebay, when I decided to try and use the headers on the module (which I had to solder on) and a max232 development board I bought to level-shift the output of the PIC.

It worked, must have a duff RS232 9-D socket or something!!

Anyway this makes it much easier and I can now develop the C code for the incoming call :)

NOTE:

The TxDo on the TC35 goes to the RxD on the MAX232 header.
Power is taken from the TC35 VDD to power the MAX232 module (5V ish).
GND on the TC35 has to be connected to GND.
It doesn't seem so important that the MAX232 module has its GND connected.

Sunday 19 October 2014

New dialler code

This is the schematic for the dialler to GMS module.

Below is a representation of a dialled number:

---------------_-_-_-_------------_-_-_-_-_-_----------

would be "35". The long pulse as the rotary is rotated anti-clockwise then the pulses for the number as the rotary returns. So when a long pulse is received, the previous set of pulses has finished and the count of these pulses is saved as the number.

The code is much simpler: (Note to self: this is in a file called push_button.c for some strange reason!)

void getNumber() {
   int16 x = 0;  // number lemgth
   int16 count = 0; // button press count
   int16 pulseCount = 0; // counts the pulses from the rotary
   int32 timer; // This is the timer
   BYTE status; // This if for detecting button state
   char phoneNum[15] = ""; // A character array for the phone number
   char num[4] = "ATD"; // start of the dial string
   strcat(phoneNum,num); // cp the start of the dial string to the phone num AT command


    // do this while the phone is still off the hook
    while (!input(PIN_A1)) {

      if (input (PIN_A0)) // dialer input high
      {
         delay_ms(10); // debounce
         pulseCount++; // This counts the number of clock cycles
         status=0;
         timer=0;
      }

      if (!input (PIN_A0) && status == 0 ) // dialer input low
      {
         delay_ms(10); // debounce switch
         if(pulseCount > 20 && count>0) { // add the count to the AT string
            count--; // decrement as the number is always one more
            if(count > 9)
               count=0;
            sprintf(num,"%ld",count); // makes int count into a string
            strcat(phoneNum,num); // adds num to the phoneNumber
            count=0; // reset the number count
            x++;
         } else {
            count++; // increment the number count
            status=1;
         }
         pulseCount=0;
      }


      // long delay before writing the AT command to GSM
      if( timer > 150000 && x > 0 ) {
         // add the final number
         count--;
         if(count > 9) // if the pulse count is 10 then this is actually a zero
            count=0;
         sprintf(num,"%ld",count); // makes int count into a string
         strcat(phoneNum,num); // adds num to the phoneNumber
         timer=0;
         x=0;     // reset number count
         count=0; // reset pulse count
         printf("%s;\r",phoneNum); // This is the AT command sent to the phone
         while(!input(PIN_A1)); // wait for on hook.
         return;

      }
      timer++;
   }

Saturday 18 October 2014

Phone call placed with PIC!

I have done the first end-to-end demonstration of dialling a number with the rotary dialler and placing a call using the Seimens T30 phone module via a MAX232.

The only problem I had was that I'd bought a passthrough RS232 cable instead of a cross over (aka "null modem cable". This basically makes the output of the RS232 the input to the phone by crossing over the Rx & Tx.

I achieved this by stuffing some wires in until I get my new X-over cable.


Next step is to improve the dialling detection. Currently I am waiting about 1 second after the last received pulse to determine the end of the dial to add the number to the AT string. At the beginning of the dial there is a long pulse as you rotate the rotary anti-clockwise, I will try and use this to indicate the the previous number has been dialled.

Sunday 12 October 2014

Dialler working...


The dialler now works, I have hooked up the rotary dial unit from the GPO phone to the circuit and all numbers are decoded correctly (most of the time) and sent to the RS232 port.




I am waiting for a RS232 - RS232 cable to send the AT command straight to the GSM module.

I had problems with switch bounce from the rotary, but this is almost eliminated with the introduction of 10ms delays after the port on the PIC is read.



The code so far:

#include "C:\Users\Daddy\Documents\CCS\push_button.h"
#include <stdio.h>
#use delay(clock=8000000) // 8MHz
#use rs232(baud=9600, xmit=PIN_B7, rcv=PIN_B5,bits=8)


void getNumber();
void checkOnHook(void);

void main(void)
{
   printf("::main()\n\r");

   // set stuff up
   setup_adc_ports (NO_ANALOGS|VSS_VDD);
   setup_adc (ADC_OFF);
   setup_spi (FALSE);
   setup_oscillator(OSC_8MHz);

   // This is the main loop
   while(true) {
      checkOnHook(); // this will wait for an incomming call
      getNumber(); // gets number from rotary and sends AT command
   }
}

// Checks if the phone is on the hook via A1
void checkOnHook(void) {
   BYTE flag=0;
   printf("::checkOnHook()\n\r");
   // RA1 the ON/OFF Hook detection
   while(input(PIN_A1)){
   // waiting for an incoming call
      if(flag==0) {
         printf("waiting for an incomming call!\n\r");
         flag=1;
      }
   }
   return;
}

// This function returns a char array that is the AT command
void getNumber() {
   int16 x = 0;
   int16 count = 0; // button press count
   int32 timer; // This is the timer
   BYTE status; // This if for detecting button state
   char phoneNum[15] = ""; // A character array for the phone number
   char num[3] = "AT"; // start of the dial string
   strcat(phoneNum,num); // cp the start of the dial string to the phone num AT command
   printf("::getNumber\n\r");

   // do this while the phone is still off the hook
   while (!input(PIN_A1)) {

      if (!input (PIN_A0) && status == 0) //input button
      {
         status = 1;
         delay_ms (10);
         output_low(PIN_C3);
         count++;      }

      if (input (PIN_A0))
      {
         delay_ms(10); // debounce?
         output_high(PIN_C3);
         status = 0;
         timer = 0; //reset timer after a pulse has been received
       }
      // short delay for individual numbers
      if (timer > 40000 && count > 0)
      {

         x++; // increment the index by one
         count--;
         if(count > 9)
            count=0;
         sprintf(num,"%ld",count); // makes count into a string
         printf("count = %ld, %s\n\r",count,num);
         strcat(phoneNum,num); // adds num to the phoneNumber
         printf(">%s\n\r",phoneNum);
         timer = 0;
         count = 0; // reset the counter
      }
      // long delay before returning the AT command
      if( timer > 100000 && x > 0 ) {
         timer=0;
         x=0;
         count=0;
         printf("%s;\n\r",phoneNum);
         while(!input(PIN_A1)); // wait for on hook.
         return;

      }
      timer++;
   }

}

Saturday 11 October 2014

Starting again....

From now on all posts are for the new and improved version of the retro-mobile.

The software will be on a PIC microcontroller - they are obviously much smaller than a Raspberry Pi and use a lot less power! I am using the PIC16F690 coz this is the one on the "low pin count" demo board that comes with the PICkit2 programmer. The plan is to use the PIC16F913 as this has LCD driver capabilities.

The basic functionality will be the same:

  • Receive call from GSM module
  • Decode and dial number from rotary dial
  • Place call with AT command on GSM module.

I have made a start by buying a new GPO phone:


...and a GSM module...

This will be incorporated with the new ringer module - yet to be built. The original mic/speaker will be replaced with some more modern 8ohm ones - should give a clear sound.

I've also completed the C code to decode the dialling and produce the AT command. I've been testing this with an RS232 to USB cable into my Win7 laptop using RealTerm. The AT command is just the unaltered output from the PIC16F690's UART TX PIN. When I was researching this I was under the impression that I needed a MAX232 to produce a text string that could be read by RS232.

I haven't tried to simulate any RS232 input to the PIC yet - this may require a MAX232 - one on order just in case!

C code to follow - it's not as nice as Python (or Java!)


Wednesday 16 April 2014

Latest Version update...the ringer

The ringer circuit is complicated, quite large and subject to blowing up PICs and H-bridges.

Ringer circuit fitted in a phone

This ringer circuit produces a 50V square wave and pulses the existing solenoids which activate the hammer on the two bell. I have decided that it is too big for the phone so another solution is needed so that I can still use the bells in the GPO phone.

Whilst retaining the bells, I have got rid of the 2 solenoids altogether as they are also quite big. So in order to ring the two bells in the phone I have decided that I need a bicycle bell. Well sort of, the mechanism an old fashioned cycle bell uses to spin round and hit the internal sides of the bell itself. This will be replicated using an electric motor, which will spin the 'dingers' against the sides of the 2 bells.

For this purpose I bought a stepper motor as this can be controlled easily with the outputs from a PIC micro controller, which I will  be using anyway to decode the dialled number from the rotary.

I built a circuit using the PICKit2 demo board - which has a 16f690 installed in it - to send the required pulses to the stepper motor controller.



Once I'd found the PIC16F690 datasheet I decided to program the very simple logic using the native assembly language, this initially proved to be quite tricky. (I spent a few years writing assembly for flight control software as a job, but this was nearly 20 years ago!). After searching for tutorials and rereading the datasheet, I had a "light bulb" moment and it all became fairly straight forward.

Using MPLAB 8, I wrote a simple program that sends a pulse-train to the 4 inputs of the stepper motor, the speed of the pulses and hence the stepper is controlled by the POT on the demo board.

Basically the program does the following:

;  Wire 1 2 3 4 5 6 7 8 Port
;  ORG  x x           x C0
;  YEL    x x x         C1
;  PIK        x x x     C2
;  BLU            x x x C3


This is the pulses that have to be sent to the stepper, so orange, then orange + yellow, then yellow etc. this is the half drive for the stepper.

The ports are the ports on the PIC used for output of the pulse.

Here's the source:

;
#include <p16F690.inc>

    __config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _BOD_OFF & _IESO_OFF & _FCMEN_OFF)


; Registers for use with the variable delay loop.
    UDATA
dc1 res 1   ; Reserve 1 byte of data memory and call it dc1
dc2 res 1   ; Reserve 1 byte of data memory and call it dc2
dc3 res 1   ; Reserve 1 byte of data memory and call it dc3


    org 0   ; start vector

Start
    BSF        STATUS,RP0  ; set bit at RP0 in register STATUS to select bank 1
    movlw    0h            ; 00000000 - makes ports C0 & C1 as outputs
    movwf    TRISC         ; moves the 00000000 to TRISC
    BCF        STATUS,RP0  ; clear bit at RP0 in register STATUS to reselect bank 0
    ; Setup the ADC
    ; NOTE: you can set these bits individually using "bsf register,bit"
    movlw    b'001'        ; set the sample rate to /8
    movwf     ADCON1       ; move to ADCON1
    ; The below 2 statements are the same as the 3rd
;    movlw    b'00000001'  ; switch A2D on
;    movwf    ADCON0
    bsf        ADCON0,ADON  ; Sets the ADON bit in ADCON0
Loop
    call A2D
    bsf        PORTC,RC0    ; C0 - using bsf does not alter content of w so means the A2D is detected
    call A2D
;    bsf        PORTC,RC0
;    bsf        PORTC,RC1
    movlw     b'00000011'   ; C0 & C1 - could set ports like this, but done for the above reason.
    movwf    PORTC
    call A2D
    bsf        PORTC,RC1    ; C2
    call A2D
    movlw     b'00000110'   ; C0 & C1 - could set ports like this, but done for the above reason.
    movwf    PORTC
    call A2D
    bsf        PORTC,RC2    ; C3
    call A2D
    movlw     b'00001100'   ; C0 & C1 - could set ports like this, but done for the above reason.
    movwf    PORTC
    call A2D
    bsf        PORTC,RC3    ; C3
    call A2D
    movlw     b'00001001'   ; C0 & C1 - could set ports like this, but done for the above reason.
    movwf    PORTC
    GOTO Loop               ; go to Loop label
   

; 10 millisecond delay loop - altered to speed it up
; setting W to 1 will be a
delay10   
    movwf    dc3       ; move value in w to memory location dc3
dly2
    movlw     .1       ; Repeat inner loop 1 times (was 13) - this speeds it up for stepper motor
    movwf    dc2       ; move .13 to memory location dc2
    clrf     dc1       ; clear dc1
dly1   
    decfsz  dc1,f      ; decrement value at dc1 to 0 then jump
    goto    dly1   
    decfsz  dc2,f      ; decrement value at dc2 to 0 then jump
    goto    dly1
    decfsz  dc3,f      ; decrement value at dc3 to 0 then jump
    goto    dly2
    return


A2D:
    bsf ADCON0,GO     ; start conversion
    btfss ADCON0,GO   

    ; if ADCON0 == 0 then jump (this bit will change to zero when the conversion is complete)
    goto $-1          ; goto previous line
    movf ADRESH,w     ; Copy the value to the w register
    ADDLW     1       ; Add 1 so that the minimum value is always > 1
    call delay10      ; calls the delay script once the value has been read from the POT
    return