TPS-Digital Means-Frequency Generator for development System

Earl

TPS-Digital Means-Frequency Generator for development System
«  »Last edited
When I was working building Stan’s TPS and Digital Means boards I wondered if I could duplicate their function using an Arduino UNO. I did try to do that but was not very happy with the results as the frequency was not very stable.  I had looked at the Arduino PWM function as it does generate a wave train where you can vary the duty cycle, used to power motors for example.  However, this only works at specify set frequencies.  I also checked to see if there were any other circuits that were now available to vary duty cycle and could not find anything other than function generators.

 I recently purchased an Arduino and experiment kit for my grandson so I thought I should brush up my Arduino knowledge and decided to take another look at using an Arduino UNO to simulate the TPS and Digital means boards. 

My plans were to use a potentiometer as the TPS input to vary the duty cycle and use a frequency input as reference way train.  Turned out I had problems accepting a low frequency input to use as a reference and wound up generating the frequency on the UNO using a second potentiometer.  Once the desired frequency is set this pot can either be turned off with a switch so it does not change, or you can hard set frequency in code. There are comments in code and more detail in attached document.

I then searched the internet to see if I could find out if anyone had done something similar without much success.  I did find that functions that allow the PWM to change duty cycle do not work below 100Hz and it even hard for normal frequency functions to work at low frequencies.  After reading several articles and help requests, I finally found references to using the Arduino registers to generate low frequencies. Several provided code samples that said how to do this but did not explain why or that the names they were using were low-level standard names that complier knows how to use. They also used binary and hex values to set the register content.

I finally found 2 good articles that were a great help.  The first explained the register structure and all the built-in names for each bit.  It also showed how to set the bits to set the mode of operation (first built-in register). The second article used this register name to set mode but in detail explained how to set second register name which sets frequency that is used by PWM function and shows how to set the duty cycle.

Once I understood how to use the registers it was easy to build, and test see pictures and code below. 

NOTE:  The attached document has all the pictures, code, and more detail on references that explain how to use registers.  It also has an example of how I set frequency in code with notes on problems I had and things to look out for.

The first picture is my test setup.  Display is showing output and its inverse as Digital Means outputs both.


Earl

Re: TPS-Digital Means-Frequency Generator for development System
« Reply #2,  »
Arduino UNO and interface board.
White cord on right USB interface, power and program upload
Pot on left sets frequency
Pot on right sets duty cycle
Swith lower right (green and brown jumpers) lock frequency when closed
IC on left is 7408 to buffer UNO output
IC on right is 7404 inverts 7408 output



Earl

Re: TPS-Digital Means-Frequency Generator for development System
« Reply #4,  »
Yellow is output frequency from UNO and 7408 blue is inverse set from 7404 while the Arduino can output these directly it is better to use these chips to buffer the output as Arduino's do not hand high loads.  These are the same chips on output of Digital Mean board.  I only wire one of each here.



Earl

Re: TPS-Digital Means-Frequency Generator for development System
« Reply #7,  »
*  This code simulates Stanley Meyers TPS, Digital Means and Frequency Generator boards
* Input is Board power, 2 Pots one to generate and vary frequency second to vary duty cycle
* Output is a digital pulse trains at set frequency and duty cyle
* Optional ICD if used provide buffer output and inverse of digital signal no change to code
*/

#include <Wire.h> //allows communication to i2c device in this case LCD display
#include <LiquidCrystal_I2C.h> //interface for LCD screens
LiquidCrystal_I2C lcd (0x27, 20, 4);  //set the LCD communicatin address; Format (address, columns, rows)

float freq = 0.0;
float duty = 0.0;

int freqChange = A0;  //Pin Change OCRA1A value Freq
int dutyChange = A1;  //Pin Change OCRA1B value Duty
int freqReadsw = 4;   //Pin to hold value of frequency Pot static
int N = 1024;  // set to match prescaler value desired
int sw = 1;  // valuable to hold swith status  High closed LOW open
long tempOCR1A = 155;
long tempOCR1B = 10;
long FreqPot = 0;
long DutyPot = 0;


void setup() {
lcd.init();  //initalize LCD screen
lcd.backlight();  //turn on backlight

// Follow code from PWM_PLAGROUON_CODE on Arduino site
// Just Pin 10:
  //Formula: wave frequency=fclk/((OCR1A+1)*N) Where N is the prescaler value
  pinMode(10, OUTPUT); // output pin for frequency, this is Arduino pin number
  pinMode(freqChange, INPUT);  // input pin to change OCR1A  Freq
  pinMode(dutyChange, INPUT);  // input to change OCR1B  Duty
  pinMode(freqReadsw, INPUT_PULLUP);  //PULL_UP reduce outside noise - connect sw to ground to use
  TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(WGM11) | _BV(WGM10); // fast PWM, 10bit resolution
  //uncomment for your desired prescaler:
  //TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // no prescaling
  //TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS11); // prescaler=8
  //TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS11) | _BV(CS10); // prescaler=64
  //TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS12); // prescaler=256
  TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS12) | _BV(CS10); // prescaler=1024
OCR1A = 40; // counter limit: 65535
OCR1B = 10; //duty cycle, can't be greater than OCR1A. (OCR1B=0.5*OCR1A for 50% duty cycle)
//duty cycle =OCR1B/OCR1A

}

/* The above sets the initial conditions for the frequency note duty cycle value will vary with value of
* OCR1A.  Once set the loop below can be used to change frequency and duty cycle need to follow note on
*duty cycle above. The smaller the value of OCR1A the larger the frequency
*/
void loop() {
  /*  I played around with the ranges in the map functions for freq and duty cycle
  *  to get the ranges I wanted as both the pot range and voltage ranges are off slightly
  *  also the duty range changes with frequency set by OCR1A
  */

  sw = digitalRead(freqReadsw);  //read state of switch
  /* Following "if" statement allows you to freeze changes to frequency by turning switch Off (open)
   * useful during testing or on bench use to keep from changing frequency by mistake
   * However value will reset to value set for tempOCR1A above if switch is closed when board restarted
   * Set tempOCR1A above to value for desired freq will always use that value when board is restarted
   * To always use a single freq set tempOCR1A  to value displayed for OCR1A on LCD and
   * comment out if statement and code in it.
   * Note: Setting tempOCR1A value directly in code gives finer control of freq than using POT
   */

 if (sw >= HIGH){
    FreqPot = analogRead(freqChange);  //Read POT value that change freq sw connect to ground
    tempOCR1A = map(FreqPot, 0, 1024, 100, 700);
     }
  DutyPot = analogRead(dutyChange);   //Read POT value to change duty cycle
  tempOCR1B = map(DutyPot, 20, 1023, 5, tempOCR1A+20);  // needs to always be smaller that OCR1A
 

  OCR1A = tempOCR1A;  //use 155 for upper range of 100Hz, 1000 for 15.63Hz
  OCR1B = tempOCR1B;
 
  freq = float(16000000)/((float(tempOCR1A+1))*N); // Freq is inverse relation to OCR1A

  lcd.setCursor(0, 0);  // set column 0 and row 0
  lcd.print("Freq ");
  lcd.print(freq);
  lcd.print(" Hz");

  duty = float(tempOCR1B)/float(tempOCR1A) * 100.0;
  //duty = float(72)/float(155);
  lcd.setCursor(0, 1);
  lcd.print("Duty ");
  lcd.print(duty);
  lcd.print( " %");

  /*  Following print statements are used to help set ranges can be left
  *  in running code  */
  lcd.setCursor(0, 2);
  lcd.print("OCR1A "); 
  lcd.print(tempOCR1A);

  lcd.setCursor(0, 3);
  lcd.print("OCR1B ");
  lcd.print(tempOCR1B);
 
}



TwistedFreq

Re: TPS-Digital Means-Frequency Generator for development System
« Reply #10,  »
Earl,

This is the best way to do this in my personal opinion as it can easily be replicated and the code can be widely distributed. I have been looking for this very set up since they introduced these kits but never felt I had the time to fab it up from scratch. Shouldn't it be easy to program in a scan and floating frequency lock as well? I am going to take some time to digest this material and get an Arduino UNO on order. If we can mix an Arduino set up with 3D printed cells even school children can make this work.

Earl

Re: TPS-Digital Means-Frequency Generator for development System
« Reply #11,  »
This setup is for the front end of Stan's system.  He actually generators frequency in several places in his system.  On frequency generator reference card.  The gate generator card, the card that generators center reference and finally on the VIC card that floats to match water being used.

One of my problems with UNO code and other projects if you are trying to duplicate things is there is usually not enough information.  For example, in here Ronnie says you need to tune VIC for each voltage level as you condition cell.  I still do not know what that means, and it is still bugging me.

The UNO is fairly easy to use I just purchased a UNO expanded Kit for my 9-year-old grandson. Having said that the register stuff referenced about was not easy to figure out and I have a degree in computer science.  Still the biggest problem was finding a good explanation of how they work I need good examples with well documented comments.

Earl

Re: TPS-Digital Means-Frequency Generator for development System
« Reply #12,  »
If you know the frequency you want to use the following equation allows you to determine value for OCR1A.  I had not included this in information above.

If you use Formula for “wave frequency=fclk/((OCR1A+1)*N) Where N is the prescaler value” and know the desired frequency and solve it for OCR1A you get:

OCR1A = (fclk/(Freq x N)) - 1
   Fclk is the clock speed of the chip so changes depending on board being used.
   N is the prescaler valve you select to give desired operational range. You choose the prescaler valve to allow finer control in
     desired frequency.
   1 is added to prevent divide by zero as OCR1A can be zero.

NOTE: OCR1A is always an integer value.

Evengravy

Re: TPS-Digital Means-Frequency Generator for development System
« Reply #13,  »
Hi Earl. Nice job. I do quite a bit of work with arduino but messing with the registers is not simple to wrap the old head around. In those case id suggest two things. 1. Look at using teensy instead (faster/easier to implement) 2. Get some help from AI with the code. I am not a massive fan of chat gpt but one thing it does well is spit out coding. Personally I would go the teensy route as a lot of the hard work is already done on backend libraries and performance is there out of the gate

securesupplies

Re: TPS-Digital Means-Frequency Generator for development System
« Reply #14,  »Last edited
it seams this signal once passing out of the gate and analogue voltage card will drive the Round bobbin also.

We have managed  to get the Schematic closer,

I welcome comments or review of attached  injector card or distributor card there is some speculation on the DB9 sign in from tps/ gas side gms cards to injectors and coil as it looks to be a shared signal in injector side 
it is represent by a grey colored line which split near the DB 9 in and splits to be grey line into injector cards and red into round bobbin.

but may be different. i welcome comments

this file should be high resolution but if not just ask i send one in png

Dan