Skip to content

Instantly share code, notes, and snippets.

@jackdev23
Created December 9, 2013 17:36
Show Gist options
  • Save jackdev23/7876502 to your computer and use it in GitHub Desktop.
Save jackdev23/7876502 to your computer and use it in GitHub Desktop.
Arduino: Antenna_analyzer_1.2
/////////////////////////////
//Antenna analyzer KL V1.2 //
/////////////////////////////
/** Copyright 2013 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 "U8glib.h"
#include "M2tk.h"
#include "utility/m2ghu8g.h"
#include <AH_AD9850.h>
U8GLIB_PCD8544 u8g(8, 9, 11, 10, 13);
AH_AD9850 AD9850(5, 6, 7, 4); //AH_AD9850(int CLK, int FQUP, int BitData, int RESET);
float freqCenter;
float stepSpan;
float bandSwr[5];
float freqBand[5] = {3650000.0, 7100000.0, 14175000.0, 21225000.0, 28850000.0};
byte SWR[84];
//byte Z[84];
float minSwr;
float maxSwr;
uint32_t next_state_sweep = 0;
byte select_display = 0;
uint32_t center_value = 0;
uint32_t span_value = 0;
//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 = 5.0*analogRead(A2)/1023;
Adcmagnitude = 5.0*analogRead(A0)/1023;
Returnloss = (60.0 * Adcmagnitude /refer);
Returnloss = Returnloss - 30.0 + 7.7656 ;
Angle = (180.0 * Adcphase /refer)- 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);
}
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 freq;
freq = freqCenter + (k-42)* stepSpan;
AD9850.set_frequency(freq);
delay(10);
Docalcswr();
if (Swr < 1.1) Swr = 1.1;
if (Swr > 3.0) Swr = 3.0;
SWR[k] = 54 -(18*Swr); //MAX SWR = 3.0
if (minSwr > Swr) minSwr = Swr;
if (maxSwr < Swr) maxSwr = Swr;
// Z[k] = 36 -(0.24* min(Zimpl,150));
}
void creaGrid(){
u8g.setFont(u8g_font_u8glib_4);
for (int i = 1 ;i < 3; i++){
u8g.drawHLine(0,i*12,83);
}
for (int i = 1 ;i < 7; i++){
u8g.drawVLine(i*12,0,36);
}
u8g.setPrintPos(0, 42);
u8g.print((freqCenter - 42*stepSpan)/1000000,3);
u8g.setPrintPos(30, 42);
u8g.print(freqCenter/1000000,3);
u8g.setPrintPos(60, 42);
u8g.print((freqCenter + 42*stepSpan)/1000000,3);
u8g.setPrintPos(0, 48);
u8g.print("SWR");
u8g.setPrintPos(30, 48);
u8g.print(minSwr, 2);
u8g.setPrintPos(60, 48);
u8g.print(maxSwr, 2);
u8g.drawRFrame(0,0,84,36, 1);
}
void printSwr(){
for (int k = 0;k < 83; 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(30, 10+pos, 53*((min(swrVal,2.5)-1.0)/1.5), 5);
u8g.drawFrame(30, 10+pos, 53, 5);
u8g.drawVLine(48, 10+pos,4);
u8g.drawVLine(65, 10+pos,4);
}
void creaBand(){
u8g.setPrintPos(45,8);
u8g.print(1.5,1);
u8g.setPrintPos(62,8);
u8g.print(2.0,1);
for (int i = 0 ;i < 5; i++){
u8g_uint_t pos = 8*i;
u8g.setPrintPos(0, 15+pos);
u8g.print(freqBand[i]/1000000,3);
swrFrame(pos,bandSwr[i]);
}
}
void barraZ(u8g_uint_t pos, float val){
u8g.drawBox(30 , pos, 53*((min(val,100))/100), 5);
u8g.drawFrame(30 , pos, 53, 5);
u8g.drawVLine(56,pos,4);
u8g.setPrintPos(10,pos+7);
u8g.print(val,1);
}
void creaZimp(){
u8g.setPrintPos(0,8);
u8g.print("freq:");
u8g.setPrintPos(30,8);
u8g.print(freqCenter,0);
u8g.setPrintPos(0,17);
u8g.print("SWR");
swrFrame(0,Swr);
u8g.setPrintPos(0,27);
u8g.print("R");
barraZ(20,Rimp);
u8g.setPrintPos(0,37);
u8g.print("X");
barraZ(30,Ximp);
u8g.setPrintPos(0,47);
u8g.print("Z");
barraZ(40,Zimpl);
}
uint8_t uiKeyUpPin = 2;
uint8_t uiKeyDownPin = 3;
uint8_t uiKeySelectPin = 12;
M2_EXTERN_ALIGN(el_top);
M2tk m2(&el_top, m2_es_arduino_rotary_encoder, m2_eh_4bs, m2_gh_u8g_ffs);
uint32_t u32_freq(m2_rom_void_p element, uint8_t msg, uint32_t val)
{
if ( msg == M2_U32_MSG_SET_VALUE ){
center_value = val;
freqCenter = (float)center_value;
}
return center_value;
}
uint32_t u32_span(m2_rom_void_p element, uint8_t msg, uint32_t val)
{
if ( msg == M2_U32_MSG_SET_VALUE ){
span_value = val;
}
if ( msg == M2_U32_MSG_GET_VALUE ){
if (span_value > 2*center_value)
span_value = 0;
}
stepSpan = (float)(span_value/84);
return span_value;
}
M2_LABEL(el_label1, NULL, "freq:");
M2_U32NUMFN(el_u8_cb, "a1.6c8", u32_freq);
M2_LABEL(el_label2, NULL, "span: ");
M2_U32NUMFN(el_span, "a1.6c8", u32_span);
void fn_details(m2_el_fnarg_p fnarg) {
select_display = 2;
m2.setRoot(&m2_null_element); // selecting this, will remove all menues
}
void fn_5_band(m2_el_fnarg_p fnarg) {
select_display = 1;
m2.setRoot(&m2_null_element); // selecting this, will remove all menues
}
void fn_ok(m2_el_fnarg_p fnarg) {
select_display = 0;
m2.setRoot(&m2_null_element); // selecting this, will remove all menues
}
void fn_reset(m2_el_fnarg_p fnarg) {
center_value = 7100000;
freqCenter = 7100000.0;
span_value = 1000000;
stepSpan = 1000000.0;
}
M2_BUTTON(el_details, "f4", "R-X-Z", fn_details);
M2_BUTTON(el_5_band, "f4", "5-Band", fn_5_band);
M2_BUTTON(el_ok, "f4", "Ok", fn_ok);
M2_BUTTON(el_reset, "f4", "Reset", fn_reset);
M2_LIST(list) = {
&el_label1, &el_u8_cb,
&el_label2, &el_span,
&el_details,&el_5_band,
&el_reset,&el_ok
};
M2_GRIDLIST(el_top_grid, "c2",list);
M2_ALIGN(el_top, "-1|1W64H64", &el_top_grid);
uint8_t update_graph_Zimp(void) {
if ( next_state_sweep < 2) {
Docalcall();
next_state_sweep++;
return 0;
}else{
next_state_sweep = 0;
return 1;
}
}
uint8_t update_graph_band(void) {
if ( next_state_sweep < 5) {
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 < 84) {
if(next_state_sweep == 0){
minSwr = 10.0;
maxSwr = 1.0;
}
calcParameters(next_state_sweep);
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) {
if ( m2.getRoot() == &m2_null_element ) {
// check for any keys and assign a suitable menu again
if ( m2.getKey() != M2_KEY_NONE ) {
m2.setRoot(&el_top);
select_display = 0;
}
switch (select_display){
case 1: return update_graph_band();
break;
case 2: {
AD9850.set_frequency(freqCenter);
return update_graph_Zimp();
}
break;
default: return update_graph();
}
}
// no update for the graphics required
return 0;
}
//================================================================
// overall draw procedure for u8glib
void draw(void) {
if ( m2.getRoot() == &m2_null_element ) {
u8g.setDefaultForegroundColor();
switch (select_display){
case 1: creaBand();
break;
case 2: creaZimp();
break;
default:
{ creaGrid();
printSwr();
}
}
}
m2.draw();
}
//================================================================
// Arduino setup and loop
void setup(void) {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
// Connect u8glib with m2tklib
m2_SetU8g(u8g.getU8g(), m2_u8g_box_icon);
m2.setFont(0, u8g_font_04b_03);
u8g.setFont(u8g_font_04b_03);
// define button for the select message
m2.setPin(M2_KEY_SELECT, 12); // dogm128 shield, 2nd from top
// The incremental rotary encoder is conected to these two pins
m2.setPin(M2_KEY_ROT_ENC_A, 3);
m2.setPin(M2_KEY_ROT_ENC_B, 2);
AD9850.reset(); //reset module
delay(1000);
AD9850.powerDown(); //set signal output to LOW
center_value = 7100000;
freqCenter = 7100000.0;
// freqCenter = (float)(readEEprom(0) * 100);
span_value = 1000000;
stepSpan = 1000000.0;
// stepSpan = (float)(100*readEEprom(4)/84);
AD9850.set_frequency(0,0,freqCenter);
}
void loop() {
m2.checkKey();
if ( m2.handleKey() != 0 || update_graphics() != 0 ) {
u8g.firstPage();
do {
m2.checkKey();
draw();
} while( u8g.nextPage() );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment