Skip to content

Instantly share code, notes, and snippets.

@jackdev23
Last active October 6, 2015 23:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jackdev23/617993a82716cd28cb85 to your computer and use it in GitHub Desktop.
Save jackdev23/617993a82716cd28cb85 to your computer and use it in GitHub Desktop.
Arduino:AA_2_2
/////////////////////////////
//Antenna analyzer KL V2.2 //
/////////////////////////////
/** Copyright 2014 Luca Facchinetti, IW2NDH
All trademarks referred to in source code and documentation are copyright their respective owners.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
If you offer a hardware kit using this software, show your appreciation by sending the author
a complimentary kit or a donation to a cats refuge ;-)
*/
#include <avr/eeprom.h>
#include "U8glib.h"
// #include "M2tk.h"
// #include "utility/m2ghu8g.h"
#include <AH_AD9850.h>
#include <Rotary.h>
#include <OneButton.h>// http://www.mathertel.de/Arduino/OneButtonLibrary.aspx
U8GLIB_64128N u8g(13, 11, 10, 9, 8); //SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
AH_AD9850 AD9850(5, 6, 7, 4); //AH_AD9850(int CLK, int FQUP, int BitData, int RESET);
Rotary r = Rotary(2, 3);
// Setup a new OneButton on pin 12.
OneButton button(12,true);
float bandSwr[7];
float freqBand[7] = {3650000.0, 7100000.0,10125000.0, 14175000.0,18118000.0, 21225000.0, 28850000.0};
const byte lcdW = 128 ;
const byte lcdH = 64 ;
const byte fontWidth = 5 ;
const byte fontHeigth = 8 ;
const byte totSpan = 9;
byte SWR[lcdW];
//byte Z[84];
float minSwr;
float maxSwr;
uint32_t next_state_sweep = 0;
byte select_display = 0;
byte menu_redraw_required = 0;
byte doubleClicked = 0;
byte modSpan = 0;
byte posInput = 0;
byte sign = 0; // negative
float spanValue[totSpan] = {25000.0, 50000.0,100000.0, 250000.0,500000.0, 1000000.0, 2500000.0, 5000000.0,10000000.0};
struct settings_t
{
int spanIdx;
float freqCenter;
} settings;
//from radians to degrees
const float R2d = 57.296;
//Standard characteristic impedance
const float Z0 = 50.0;
float Angle ;
float Mag ;
float Ximp ;
float Rimp ;
float Zimpl ;
float Swr ;
void Docalcswr(){
float Tmpsa ;
float Tmpsb ;
float Tmpsc ;
//adc variables
float Adcphase;
float Adcmagnitude;
float Returnloss;
//float refer = 5.0*analogRead(A1)/1023;
Adcphase = 1.8 * analogRead(A2)/1023;
Adcmagnitude = 1.8 *analogRead(A0)/1023;
Returnloss = (60.0 * Adcmagnitude /1.8);
Returnloss = Returnloss - 30.0 -0.44;
Angle = (180.0 * Adcphase /1.8) -90;
Tmpsa = Returnloss / 20.0;
Tmpsb = 10.0;
Mag = pow(Tmpsb , Tmpsa);
Mag = 1.0 / Mag;
Tmpsa = 1.0 + Mag;
Tmpsb = 1.0 - Mag;
Tmpsc = Tmpsa / Tmpsb;
Swr = abs(Tmpsc);
Serial.print("Adcmagnitude ");
Serial.print(Adcmagnitude);
Serial.print(" Returnloss ");
Serial.println(Returnloss);
// Serial.print(" Angle ");
// Serial.print(Angle);
// Serial.print(" SWR ");
// Serial.println(Swr);
}
void Docalcall(){
Docalcswr();
float Tmpsa ;
float Tmpsb ;
float Tmpsc ;
float Rrsqrtmp ;
float Sssqrtmp ;
float F ;
float G ;
float Rr ;
float Ss ;
Tmpsa = Angle / R2d;
F = cos(Tmpsa);
G = sin(Tmpsa);
Rr = F * Mag;
Ss = G * Mag;
Tmpsa = 1.0 - Rr;
Rrsqrtmp = Tmpsa * Tmpsa;
Sssqrtmp = Ss * Ss;
Tmpsa = Rrsqrtmp + Sssqrtmp;
Tmpsb = 2.0 * Ss;
Tmpsc = Tmpsb / Tmpsa;
Tmpsa = Tmpsc * Z0;
Ximp = abs(Tmpsa);
Tmpsa = Rr * Rr;
Tmpsb = 1.0 - Tmpsa;
Tmpsa = Tmpsb - Sssqrtmp;
Tmpsb = Rrsqrtmp + Sssqrtmp;
Tmpsc = Tmpsa / Tmpsb;
Tmpsa = Tmpsc * Z0;
Rimp = abs(Tmpsa);
Tmpsa = Rimp * Rimp;
Tmpsb = Ximp * Ximp;
Tmpsc = Tmpsa + Tmpsb;
Zimpl = sqrt(Tmpsc);
}
void calcParameters(int k, float stepSpan){
float freq;
float tempSwr;
freq = settings.freqCenter + (k-lcdW/2)* stepSpan;
if (freq <= 0) freq = 1000000.0;
AD9850.set_frequency(freq);
delay(10);
Docalcswr();
Swr = max(1.1,Swr);
minSwr = min(minSwr,Swr);
maxSwr = max(maxSwr,Swr);
tempSwr = min (3.0, Swr);
SWR[k] = 8+(46 - round(23*(tempSwr - 1))); //MAX SWR = 3.0
}
void printReverse(u8g_uint_t x, u8g_uint_t y,const char *s){
u8g_uint_t w = u8g.getStrWidth(s);
u8g.drawBox(x, y - 7, w, 9); // draw cursor bar
u8g.setDefaultBackgroundColor();
u8g.drawStr(x,y,s);
u8g.setDefaultForegroundColor();
}
void creaGrid(){
u8g_uint_t p0 = lcdH - 2;
for (int i = 1 ;i < 2; i++){
u8g.drawHLine(0,(i*22)+fontHeigth,lcdW - 1);
}
for (int i = 0 ;i < 9; i++){
u8g.drawVLine(64+(i-4)*14,fontHeigth,46);
}
u8g.drawCircle(64,49+fontHeigth,2);
if (settings.freqCenter >9999999) u8g.setPrintPos(30, p0);
else u8g.setPrintPos(35, p0);
u8g.print(settings.freqCenter/1000000,3);
if (spanValue[settings.spanIdx] >9999999) u8g.setPrintPos(94, p0);
else u8g.setPrintPos(99, p0);
u8g.print(spanValue[settings.spanIdx]/1000000,3);
u8g.drawRFrame(0,fontHeigth,lcdW,46, 1);
u8g.drawStr(0, fontHeigth-1,"SWR");
u8g.setPrintPos(42, fontHeigth-1);
u8g.print(minSwr, 2);
u8g.setPrintPos(96, fontHeigth-1);
u8g.print(maxSwr, 2);
if (!modSpan){
printReverse(0, p0 ,"freq");
u8g.drawStr(70, p0 ,"span");
}else{
u8g.drawStr(0, p0 ,"freq");
printReverse(70, p0 ,"span");
}
}
void printSwr(){
for (int k = 0;k < lcdW -1; k++){
u8g.drawLine(k,SWR[k],k+1,SWR[k+1]);
// u8g.drawCircle(k,Z[k], 1, U8G_DRAW_ALL) ;
}
}
void swrFrame(u8g_uint_t pos, float swrVal){
u8g.drawBox(50, pos, 77*((min(swrVal,2.5)-1.0)/1.5), 6);
u8g.drawFrame(50, pos, 77, 6);
u8g.drawVLine(76, pos,5);
u8g.drawVLine(102, pos,5);
}
// void barraZ(u8g_uint_t pos, float val){
// u8g.drawBox(50, pos, 77*((min(val,100))/100), 6);
// u8g.drawFrame(50, pos, 77, 6);
// u8g.drawVLine(88,pos,6);
// u8g.setPrintPos(22,pos+7);
// u8g.print(val,1);
// }
void creaBand(){
u8g.setPrintPos(76,7);
u8g.print(1.5,1);
u8g.setPrintPos(102,7);
u8g.print(2.0,1);
for (int i = 0 ;i < 7; i++){
u8g_uint_t pos = (8 * i) + 10;
u8g.setPrintPos(0, pos + 5);
u8g.print(freqBand[i]/1000000,3);
swrFrame(pos,bandSwr[i]);
}
}
// void creaZimp(){
// u8g.drawStr(0,8,"freq:");
// if (settings.freqCenter >9999999) u8g.setPrintPos(50,8);
// else u8g.setPrintPos(56,8);
// u8g.print(settings.freqCenter,0);
// u8g.drawStr(0,18,"SWR");
// swrFrame(12,Swr);
// u8g.setPrintPos(20,18);
// u8g.print(Swr,2);
// u8g.drawStr(0,48,"R");
// barraZ(41,Rimp);
// if (sign == 0){
// u8g.drawStr(0,39,"Ph +");
// u8g.drawStr(0,55,"Xc +");
// printReverse(0,28,"short");
// }
// else {
// u8g.drawStr(0,39,"Ph -");
// u8g.drawStr(0,55,"Xl -");
// printReverse(105,28,"long");
// }
// u8g.setPrintPos(22,39);
// u8g.print(abs(Angle),1);
// barraZ(49,Ximp);
// u8g.drawStr(0,63,"Z");
// barraZ(57,Zimpl);
// }
// uint8_t update_graph_Zimp(void) {
// if ( next_state_sweep < 2) {
// // swr decrease when freq encrease <=> too short <=> X positive (C) <=> sign = 1
// AD9850.set_frequency(settings.freqCenter+100000.0);
// delay(10);
// Docalcswr();
// float upFreqSwr = Swr;
// AD9850.set_frequency(settings.freqCenter);
// delay(10);
// Docalcall();
// if (upFreqSwr > Swr)
// sign = 1;else sign = 0;
// next_state_sweep++;
// return 0;
// }else{
// next_state_sweep = 0;
// return 1;
// }
// }
uint8_t update_graph_band(void) {
if ( next_state_sweep < 7) {
AD9850.set_frequency(freqBand[next_state_sweep]);
delay(10);
Docalcswr();
bandSwr[next_state_sweep] = Swr;
next_state_sweep++;
return 0;
}else{
next_state_sweep = 0;
return 1;
}
}
uint8_t update_graph(void) {
if ( next_state_sweep < lcdW) {
if(next_state_sweep == 0){
minSwr = 10.0;
maxSwr = 1.0;
}
float s = spanValue[settings.spanIdx]/lcdW;
calcParameters(next_state_sweep,s);
next_state_sweep++;
return 0;
}else{
next_state_sweep = 0;
return 1;
}
}
// update graphics, will return none-zero if an update is required
uint8_t update_graphics(void) {
switch (select_display){
case 1: return update_graph_band();
break;
// case 2: {
// return update_graph_Zimp();
// // }
// break;
default: return update_graph();
}
// no update for the graphics required
return 0;
}
void showCursor(u8g_uint_t x0, u8g_uint_t y0){
u8g.drawBox(x0 + fontWidth*(7-posInput),y0,6,3);
}
float updateFreq(unsigned char r, float v){
float step = round(pow(10,posInput));
if (r == DIR_NONE ) {
// do nothing
}
else if (r == DIR_CW) {
v = v + step;
}
else if ((r == DIR_CCW) && (v >= step + 1000000.0)) {
v = v - step;
}
return v;
}
void updateSpan(unsigned char r){
if (r == DIR_NONE ) {
// do nothing
}
else if (r == DIR_CW) {
settings.spanIdx++;
}
else if (r == DIR_CCW) {
settings.spanIdx--;
if (settings.spanIdx < 0) settings.spanIdx = totSpan -1;
}
settings.spanIdx = settings.spanIdx % totSpan;
}
//================================================================
// overall draw procedure for u8glib
void draw(void) {
u8g.setDefaultForegroundColor();
switch (select_display){
case 1: creaBand();
break;
// case 2: {
// creaZimp();
// if (doubleClicked == 1) {
// showCursor(50,8);
// }
// }
// break;
default:
{ creaGrid();
printSwr();
if (doubleClicked == 1) {
switch (modSpan){
case 0 : {
if (posInput <3) posInput = 3; showCursor(35,lcdH-1);
break;
}
case 1 :{
posInput = 6;
showCursor(91,lcdH-1);
break;
}
default: break;
}
}
}
}
}
//================================================================
// Arduino setup and loop
void setup(void) {
analogReference(EXTERNAL);
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
//analogReference(EXTERNAL);
// pinMode(12, INPUT);
// digitalWrite(12,HIGH);
PCICR |= (1 << PCIE2);
PCMSK2 |= (1 << PCINT18) | (1 << PCINT19) ;
// PCICR |= (1 << PCIE0);
// PCMSK0 |= (1 << PCINT4);
sei();
// link the doubleclick function to be called on a doubleclick event.
button.attachDoubleClick(doubleclick);
button.attachClick(singleclick);
button.attachPress(longclick);
u8g.setFont(u8g_font_5x7);
eeprom_read_block((void*)&settings, (void*)0, sizeof(settings));
settings.spanIdx = settings.spanIdx % totSpan;
if (settings.freqCenter <= 0)
{
settings.freqCenter = 7000000.0;
}
settings.spanIdx = 0;
settings.freqCenter = 7000000.0;
AD9850.reset(); //reset module
delay(1000);
AD9850.powerDown(); //set signal output to LOW
AD9850.set_frequency(0,0,settings.freqCenter);
}
void loop() {
button.tick();
if ( update_graphics() != 0 | menu_redraw_required != 0) {
u8g.firstPage();
do {
draw();
} while( u8g.nextPage() );
menu_redraw_required = 0; // menu updated, reset redraw flag
}
}
ISR(PCINT2_vect) {
unsigned char result = r.process();
if (doubleClicked)
{
if((select_display == 0) && modSpan){
updateSpan(result);
}
else
settings.freqCenter = updateFreq(result, settings.freqCenter);
}
else if(select_display == 0) modSpan = !modSpan;
menu_redraw_required = 1;
}
void singleclick() {//change position in field
if (doubleClicked) {
posInput++;
posInput = posInput % 7;
}
menu_redraw_required = 1;
}
void doubleclick() { //change field
doubleClicked = !doubleClicked;
if (!doubleClicked) eeprom_write_block((const void*)&settings, (void*)0, sizeof(settings));;
menu_redraw_required = 1;
}
void longclick() { //rotate displays
select_display = select_display++;
select_display = select_display % 3;
posInput = 0;
doubleClicked = 0;
eeprom_write_block((const void*)&settings, (void*)0, sizeof(settings));
menu_redraw_required = 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment