Category Archives: Posts

Here will post many things.

ATtiny85 Bricked? No problem!

Messing with fuses may brick ATtiny85!

On Attiny85 (also on other Attiny__) chips from Atmel, I recently made mistake, not knowing exact ‘truth’ about how to set fuses properly, so that it work as expected. The problem is in online documentation and implementation in some of available programmers as is “Khazama AVR programmer”. Even online calculator is wrong – if for example you want to use 8 MHz and above external quartz crystal oscillator, then you should select CSEL = 1110, but calculator showing that three boxes should be unchecked (CSEL[3:1]), while last box (CSEL0) should be checked. THIS IS NOT TRUE!!! If you look in datasheet about Attiny85, then it is exactly 1110, but online calculators, and programmer showing confusing and contradictory messages about what enables or disables what. So, I made (not so short) video about this issue + how to ‘un-brick’ Bricked Attiny__ (in my case Attiny85).

Is there hope for bricked chip?

YES! Bricked Attiny85 simply does not accept ISP programmer, but it can be ‘rescued’ by so called “HV programming”, where high voltage is actually 12V to the reset pin (pin number 1 on Attiny85), then some weird commutation of +5V and +12V on the chip brings it into programming mode. Down below is diagram and sketch, which is not my idea, but rather I with to thanks and give credit to those people who designed it and modified so that we can rescue our favorite chips.

On the image above, there is credit to someone who made it possible, but someone else changed sketch slightly, so that it now works as is expected.

The sketch for Arduino nano:

// AVR High-voltage Serial Fuse Reprogrammer
 // Adapted from code and design by Paul Willoughby 03/20/2010
 // http://www.rickety.us/2010/03/arduino-avr-high-voltage-serial-programmer/
 // Fuse Calc:
 // http://www.engbedded.com/fusecalc/

 #define RST 13 // Output to level shifter for !RESET from transistor
 #define SCI 12 // Target Clock Input
 #define SDO 11 // Target Data Output
 #define SII 10 // Target Instruction Input
 #define SDI 9 // Target Data Input
 #define VCC 8 // Target VCC

 #define HFUSE 0x747C
 #define LFUSE 0x646C
 #define EFUSE 0x666E

 // Define ATTiny series signatures
 #define ATTINY13 0x9007 // L: 0x6A, H: 0xFF 8 pin
 #define ATTINY24 0x910B // L: 0x62, H: 0xDF, E: 0xFF 14 pin
 #define ATTINY25 0x9108 // L: 0x62, H: 0xDF, E: 0xFF 8 pin
 #define ATTINY44 0x9207 // L: 0x62, H: 0xDF, E: 0xFFF 14 pin
 #define ATTINY45 0x9206 // L: 0x62, H: 0xDF, E: 0xFF 8 pin
 #define ATTINY84 0x930C // L: 0x62, H: 0xDF, E: 0xFFF 14 pin
 #define ATTINY85 0x930B // L: 0x62, H: 0xDF, E: 0xFF 8 pin

 void setup() {
 pinMode(VCC, OUTPUT);
 pinMode(RST, OUTPUT);
 pinMode(SDI, OUTPUT);
 pinMode(SII, OUTPUT);
 pinMode(SCI, OUTPUT);
 pinMode(SDO, OUTPUT); // Configured as input when in programming mode
 digitalWrite(RST, HIGH); // Level shifter is inverting, this shuts off 12V
 Serial.begin(19200);
 Serial.println("Code is modified by Rik. Visit riktronics.wordpress.com and electronics-lab.com for more projects");
 Serial.println("-------------------------------------------------------------------------------------------------");
 Serial.println("Enter any character to start process..");}


 void loop() {
 if (Serial.available() > 0) {
 Serial.read();
 pinMode(SDO, OUTPUT); // Set SDO to output
 digitalWrite(SDI, LOW);
 digitalWrite(SII, LOW);
 digitalWrite(SDO, LOW);
 digitalWrite(RST, HIGH); // 12v Off
 digitalWrite(VCC, HIGH); // Vcc On
 delayMicroseconds(20);
 digitalWrite(RST, LOW); // 12v On
 delayMicroseconds(10);
 pinMode(SDO, INPUT); // Set SDO to input
 delayMicroseconds(300);
 unsigned int sig = readSignature();
 Serial.println("Reading signature from connected ATtiny......");
 Serial.println("Reading complete..");
 Serial.print("Signature is: ");
 Serial.println(sig, HEX);
 readFuses();
 if (sig == ATTINY13) {

 Serial.println("The ATtiny is detected as ATtiny13/ATtiny13A..");
 Serial.print("LFUSE: ");
 writeFuse(LFUSE, 0x6A);
 Serial.print("HFUSE: ");
 writeFuse(HFUSE, 0xFF);
 Serial.println("");
 } else if (sig == ATTINY24 || sig == ATTINY44 || sig == ATTINY84 ||
 sig == ATTINY25 || sig == ATTINY45 || sig == ATTINY85) {

 Serial.println("The ATtiny is detected as "); 
 if(sig == ATTINY24) Serial.println("ATTINY24..");
 else if(sig == ATTINY44) Serial.println("ATTINY44..");
 else if(sig == ATTINY84) Serial.println("ATTINY84..");
 else if(sig == ATTINY25) Serial.println("ATTINY25..");
 else if(sig == ATTINY45) Serial.println("ATTINY45..");
 else if(sig == ATTINY85) Serial.println("ATTINY85..");
 
 writeFuse(LFUSE, 0x62);
 writeFuse(HFUSE, 0xDF);
 writeFuse(EFUSE, 0xFF);
 }

 Serial.println("Fuses will be read again to check if it's changed successfully..");
 readFuses();
 digitalWrite(SCI, LOW);
 digitalWrite(VCC, LOW); // Vcc Off
 digitalWrite(RST, HIGH); // 12v Off

 Serial.println("");
 Serial.println("");
 Serial.println("");
 Serial.println("");
 }
 }

 byte shiftOut (byte val1, byte val2) {
 int inBits = 0;
 //Wait until SDO goes high
 while (!digitalRead(SDO))
 ;
 unsigned int dout = (unsigned int) val1 << 2;
 unsigned int iout = (unsigned int) val2 << 2;
 for (int ii = 10; ii >= 0; ii--) {
 digitalWrite(SDI, !!(dout & (1 << ii)));
 digitalWrite(SII, !!(iout & (1 << ii)));
 inBits <<= 1; inBits |= digitalRead(SDO);
 digitalWrite(SCI, HIGH);
 digitalWrite(SCI, LOW);
 } 
 return inBits >> 2;
 }

 void writeFuse (unsigned int fuse, byte val) {
 
 Serial.println("Writing correct fuse settings to ATtiny.......");
 
 shiftOut(0x40, 0x4C);
 shiftOut( val, 0x2C);
 shiftOut(0x00, (byte) (fuse >> 8));
 shiftOut(0x00, (byte) fuse);

 Serial.println("Writing complete..");
 }

 void readFuses () {

 Serial.println("Reading fuse settings from connected ATtiny.......");
 
 byte val;
 shiftOut(0x04, 0x4C); // LFuse
 shiftOut(0x00, 0x68);
 val = shiftOut(0x00, 0x6C);
 Serial.print("LFuse: ");
 Serial.print(val, HEX);
 shiftOut(0x04, 0x4C); // HFuse
 shiftOut(0x00, 0x7A);
 val = shiftOut(0x00, 0x7E);
 Serial.print(", HFuse: ");
 Serial.print(val, HEX);
 shiftOut(0x04, 0x4C); // EFuse
 shiftOut(0x00, 0x6A);
 val = shiftOut(0x00, 0x6E);
 Serial.print(", EFuse: ");
 Serial.println(val, HEX);
 Serial.println("Reading complete..");
 }

 unsigned int readSignature () {
 unsigned int sig = 0;
 byte val;
 for (int ii = 1; ii < 3; ii++) {
 shiftOut(0x08, 0x4C);
 shiftOut( ii, 0x0C);
 shiftOut(0x00, 0x68);
 val = shiftOut(0x00, 0x6C);
 sig = (sig << 8) + val;
 }
 return sig;
 }

Be careful about the “Fuse calc”!!!

You may notice that “Fuse calc” gives (for example) result of 1110 for external quartz oscillator, but boxes below are incorrectly checked! Pay attention to that. Here is my video and some conclusions about that:

Instead ugly 12V lead acid battery, consider buying this 5V to 12V step-up converter.

PWM modulation as DAC on Atmega328p

PWM or Pulse Width Modulation

It is good to have 8 ADC inputs on Atmega328p, of which last one is actually thermometer inside chip, but there are no DAC converter for making sound out of digital data. Tried one DAC chip, MCP4725, which is 12 bit DAC with I2C data transfer, but turns out that it is pretty slow even at 800 kHz I2C bus. That is because of something weird inside this chip, where time required for output signal to reach maximum, starting from zero is 6 microseconds, no matter what I do. So, I decided to use PWM as possible way to do DAC conversion.

How it works?

By using fixed frequency, but variable length of the pulses, it is possible to change output voltage from digital output (!) from zero to maximum voltage, depend of voltage which is applied to Atmega328p. If pulses are narrow, then after filtering by low pass filter (RC or LC filters) – output voltage is low. If pulses are wide, voltage is higher. So, in the case of 5V on the Atmega chip, if duty cycle is 50%, then output voltage is  2.5V.

How good is sound quality?

Not so good if PWM frequency is low. Also depends of how many bits are used. If 16 bit timer is used, in theory it is possible to use all 16 bits, which will give 65536 voltage steps, but then PWM frequency will be pretty low. For driving motors or LEDs it is not a problem, but it is problem for audio applications. Some relatively good quality for voice is possible by using 62.5 kHz PWM with 8 bit resolution on Atmega328p with quartz crystal on 16 MHz. That is because Fast PWM with timer(s) and divider of F_CPU/1 (no prescalling) require 256 counts, which can be calculated by formula: FPWM=F_CPU/256. In the case of 16 MHz crystal, this is 62500 Hz, or 62.5 kHz. This frequency is pretty good for voice audio, but not so great for music. But, this is trade-off of using inexpensive way to make DAC out of this chip.

Other way than using timer(s)?

Yes. I had problem making exactly 40 kHz for ultrasonic purpose, because of all frequencies at which PWM can work, neither one can be get by using dividers, and/or number of bit manipulations. So, I made an “PWM imitation” by using two delay loops (for (;;) ), where variable delay is obtained by changing number to where loop goes. For example: “for (i=0;i<32;i++);” together with the rest of the code gives me 12.5 microseconds, which is half of 25 microseconds needed for 40 kHz (1/25 uS = 40 kHz). There are two loops, where first one gives ON time, and second one OFF time. Sum of ON+OFF time gives duty cycle in steps depending of how much bites are used. Since whole process is relatively slow, I am forced o use just 5 bites, which is okay for voice audio. This mins that 5 bites gives duty cycles in 32 steps, from near zero to maximum (which in my case is not 100% but rather close to 80% due to other commands in the C code). One of this additional codes are ADC conversion and mathematics conversion from 10 bits to 5 bits. This just slow cycles enough so that it can’t reach 100% pulse width.

The code:

// Ultrasonic parametric speaker by
// Milan Karakaš, Croatia
// https://wildlab.org
// Working, but require more investigation
// about quality... feel free to upgrade

uint8_t i;
int on=16; //halfway between 0 and 32

void setup() 
{
  DDRB |= (1<<PB0);//output for 40 kHz
  TIMSK0=0;//stops timer 0 which may cause distortions
  /*ADC setup*/
  DIDR0 = (1<<ADC0D);//disabling digital in/out, and enabling analog input on ADC0
  //ADMUX = (1<<REFS0);//reference is VCC, input is analog0, ADLAR=0 (lower 10 bits)
  ADMUX = (1<<REFS0)|(1<<REFS1);
  ADCSRA = (1<<ADEN)|(1<<ADPS1); //enabled, interrupt disabled(!),prescaller is F_CPU/4 (4 MHz, faster loop)
}

void loop() 
{
  /*PWM "imitation" at 40 kHz */
  while(1) //infinite loop, but faster than "loop()" itself!
  {
    ADCSRA |= (1<<ADSC);//start ADC conversion
    on=(ADC>>5);// ADC/32, or binary shift five to the right
    /*opens output high*/
    PORTB |= (1<<PB0); //plus delay
    for (i=0;i<on;i++);//on time is as ADC value/32
    /*closes output low*/
    PORTB &= ~(1<<PB0);
    for (i=0;i<(32-on);i++);//off time is 32-on time, always total of 25 uS (40 kHz)
  }
  /*end of PWM "imitation" at 40 kHz */
}


Note that I wrote “parametric speaker”, because this code is intended to do job, but I found many problems with sound quality out of ultrasonic speakers with this modulation. Still working on improvements. But, this code is good for exercise in advanced programming. Later on, I will make code for audio with PWM at 62.5 kHz for telecommunication purpose (voice over digital radio-modem). Here is video rant about this PWM stuff:

Enjoy!

Arduino I2C Scanner

What is the I2C address?! Scanner please.

Do I need such scanner? Sooner or later, everyone stuck on some I2C device – unknown address. For example, on OLED display, there is jumper (SMD resistor with “000” – zero Ohms), and next to it: “IIC address eslect”, and two options, soldered at first one: 0x78, and can be selected another one by removing this resistor and soldering at second place: 0x7A. But, after opening example code for this OLED display, it does not works. Why?! Because it has address of 0x3C, not 0x78 as it is designated. So, here is simple sketch I found somewhere. Well known and simple sketch, but very useful:

// --------------------------------------
//    i2c_scanner
//
//    Version 1
//    This program (or code that looks like it)
//    can be found in many places.
//    For example on the Arduino.cc forum.
//    The original author is not know.
//    Version 2, Juni 2012, Using Arduino 1.0.1
//    Adapted to be as simple as possible by Arduino.cc user Krodal
//    Version 3, Feb 26  2013
//    V3 by louarnold
//    Version 4, March 3, 2013, Using Arduino 1.0.3
//    by Arduino.cc user Krodal.
//    Changes by louarnold removed.
//    Scanning addresses changed from 0...127 to 1...119,
//    according to the i2c scanner by Nick Gammon
//    http://www.gammon.com.au/forum/?id=10896
//    Version 5, March 28, 2013
//    As version 4, but address scans now to 127.
//    A sensor seems to use address 120.
//    Version 6, November 27, 2015.
//    Added waiting for the Leonardo serial communication.
//
//
//    This sketch tests the standard 7-bit addresses
//    Devices with higher bit address might not be seen properly.
//
 
#include <Wire.h>
 
 
void setup()
{
  Wire.begin();
 
  Serial.begin(115200);
  while (!Serial);             // Leonardo: wait for serial monitor
  Serial.println("\nI2C Scanner");
}
 
 
void loop()
{
  byte error, address;
  int nDevices;
 
  Serial.println("Scanning...");
 
  nDevices = 0;
  for(address = 1; address < 127; address++ )
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
 
    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");
 
      nDevices++;
    }
    else if (error==4)
    {
      Serial.print("Unknow error at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");
 
  delay(5000);           // wait 5 seconds for next scan
}

You may use :

Serial.begin(9600);
// instead
Serial.begin(115200); 
// it is up to you which speed you will use for serial

Most of the default examples uses 9600 bits per second, but sometimes I need it faster, so I made it “115200”.  If you have problem with your serial port (USB cable to your Arduino), then lower speed, it is up to you. Just be sure to select the same speed at Serial Monitor, bottom right corner. Else it will not work.

Wiring

Instead making wiring diagram, I will just tell you that SCL and SDA of the device in question goes to SCL and SDA on your favorite  Arduino board.  Usually with numbers 4 and 5; SCL (serial clock) to pin A5 (or ADC5, or pin number 28), and SDA (seral data) to pin A4 (or ADC4, or pin number 27). Do not forget to power your device with appropriate voltage and connect ground wire. Usually it is 5V, but there may be exceptions.

It will give you info every five seconds, something like this:

DIY quadcopter: FrankenDrone

Maiden of “FrankenDrone”,  DIY quadcopter

So far, managed to record video maiden (first flight) of my new “FrankenDrone”, DIY quadcopter. It has JJ1000 controller board, gears and propellers (props) from Syma X5C, with 7×20 mm motors.

Upgrading stronger motors

Now upgraded to FY326 gearbox and motors 8.5×20 mm. My flight with Mobius camera onboard failed because microSD card has some problem with deleted files. Camera showing that it recording, but I can’t find video files on microSD card. Now, after quick format, everything works fine. Here will be updated status of the experimental flights.

The difference between gearboxes of Syma X5C and FY326 Q7

Syma X5C, as well as its clone Bayangtoys X8 has some problem with vertical “play” of the main shaft which holds props. Gearbox with motor mount and prop mount has no such problem, or it is very minimal play, maybe 0.5 mm, while Syma X5C and Bayangtoys X8 has this “movement freedom” of about 1-1.5 mm. It is not a problem during flight, since props pulling this shaft up, and gears are aligned perfectly. But, noticed that gearbox from FY326 (original designation of this quadcopter is Q7) is more silent. On Syma X5C gearbox, I can clearly hear strange noise produced by movement of pinion and gears, while on gearbox from FY326, this noise is very low.

Further improvement

Gearbox has 3 x 3 mm square profile, but I found only 3 mm round aluminium rod, and used it. The problem with this rod is that aluminium by default is hard to drill – broke 3 drills and did not make hole for screw to fix it properly. Now found better option on Aliexpress, but so far… haven’t money to buy. It will be long(ish) waiting until it happens. 🙁

Excellent carbon square,  3 x 3 mm can be found here.

For more range & installing buzzer

I already modified JJ1000 remote with “V” antenna, and should to upgrade similar antenna on the quadcopter to get maximum possible range, since I want to fly it FPV. In order to avoid duplicate post, anyone interested in extending range, can found it on my webpage here. Note that diagram on this page is for Syma X5C, and Bayangtoys X8. On JJ1000 board, installing buzzer is much simpler:

Just solder +ve of the buzzer on cahtode of the diode, and -ve on drain of the MOSFET which run on/off LEDs on the quadcopter. After binding, buzzer whistling all the time, and then press right “shoulder” button for 3 seconds to turn LEDs and buzzer off. Battery alarm will sounds and LEDs will blinks. In the case of lost quadcopter, just turn of remote, and buzzer will sounds, LEDs will blinks. Easier to found.

Choice of the buzzer

At first model of my FrankenDrone, I am using buzzer from some programmable LEDs which has buzzer in between, but this option is bit expensive. Then ordered buzzers from Aliexpress – little one, just 0.67 grams. But it is big disappointment – not loud enough. Reason why I wanted so light buzzers is to install it on smaller quadcopters, but this one is big and has no such issue with little bit heavier buzzer. This one from Banggood.com is the best option:

The rule about buzzer

For indoor flight, quiet buzzer is okay, but this makes no sense to install it when indoor flight – you always can find your quad. The louder the better. If it does not give you “instant headache” when sounds, it is not good for outdoor flight with quadcopter. Consider next situation: strong wind blows away your quadcopter, and it flyaway into some bush. The same wind may be sufficiently loud to “override” volume of some small and silent buzzers. So, louder is better. This one above is sufficiently loud, but I want more, still searching for cheap yet louder one. 🙂

Become my ‘permanent Banggood friend’ by applying this CODE if you already haven’t Banggood account. You will buy at no additional cost, and I will get some points which helps me to make more exciting projects. Thank you in advance.

Arduino altimeter

Altimeter: Another problem with losing data during lost signal:

Altimeter sketch, Tried to change library from VirtualWire.h to RadioHead.h, but memory on Arduino nano is already too much populated, working memory for variables. So… Don’t know what to do… OLED display take 1024 bytes (1 kB), maybe I should to consider different display?

Altimeter programming problems

Altimeter: some outdoor test is done with one big mistake…

This video is made before utilizing “second order temperature compensation” in sketch of the transmitter. It looks complicated, but it turns out that is actually simple to apply (or I become somewhat good in programming). 😀 What happens is that I set zero indoor where temperature is close to 20°C, but outdoor in early morning was just 7°C, which gives me error of about -6 meters. Now things are better, error is still present but no more than say – 3 meters. BUT (!), now this error is within ballpark of maximum -3 meters error if temperature changes dramatically, which in most situations is not the case. Problem may occur during winter time, when someone want to fly briefly, and bring outside “warm” quad with sensor at say 20°C, then begins to fly – when set zero on ground, fly, and back, on ground should be again zero. For this reason, give quad and sensor some time to accommodate to whatsoever temperature outdoor is. Sensor is temperature dependent, and between 20°C and maximum operating temperature of 85°C it has pretty linear reading. The problem begins below 20°C, and exponentially rise with lowering temperature. But, since we are not interested in correct atmospheric pressure, but rather correct measured altitude, such error of -3 meters (which is about 0.5 mb, or 0.5 hPa), is next to nothing if quad fly very high AND (!) in meanwhile temperatures drops drastically. Down below is sketch for Attiny85, which is now corrected with added additional math. In the worst case of temperature drop, error is no more than -16 meters at temperatures between -15°C and -40°C DIFFERENCE (!) between starting temperature and temperatured during flight. And, I doubt that anyone has actual will to fly on such cold and freezing butt temperature. 😀

Altimeter: transmitter under 3 grams! (2.75 g with antenna)

On this ‘remote’ altimeter, still need to add ISP connector with 6 wires for re-programming firmware. Just in case that something need to be changed. Else, it is under 3 grams, but as ‘features’ growing, it will be slightly above 3 grams. For example, this 1/4 lambda antenna is okay, but full dipole (1/2 lambda) is better for more range. Just need to finish receiver end, post it on this page, and test maximum possible range. I am hoping for 1 km or more, but will see. Also, not sure how it will looks like on the quadcopter. For rockets, there will be different version – one without transmitter, just recording max altitude in EEPROM, then red with some base station, but that is future plan. Or, maybe I will find some good and lightweight LCD display… don’t know… For quadcopters, it is good to monitor altitude dynamicaly – in flight, but for rockets… eh, it goes hight as it goes – no way to monitor it in real time.

Arduino Altimeter – first steps are done

Altimeter – Beta version works on 433 MHz, base station should be pressed “zero” to set zero of the vehicle (airplane, quadcopter…), and then it will calculate altitude by receiving data from vehicle to the base station. So far, I have some problem with OLED display and it’s library: it uses too much memory and some instability occurs when it is out of range and not used for longer period. Just need to see what may be done…

Download (PDF, 98KB)

Working day and night… not only this project, but other things as well. Just some short video:

On this video, pressure sensor MS5611-01BA01 is used. By clicking on this link, you will get datasheet if you are interested.

Another PDF file MS5611-01BA03, much detailed, where at pages 17, 18 and 19 – diagrams showing error in pressure and temperature measurements without applying “Second order temperature compensation”, where sensor below 20°C increasing interpreting pressure reading exponentially as temperature goes really low. This math correcting it as much as possible. Still some error remains, but with peak of about 1.8 mBar at temperatures between -15°C and -40°C. Without this, additional math, error at such temperatures are up to 28 mBar at -40°C. At some “normal” local atmospheric pressures of say 1000 mBar, error of 1 mBar equals 8.426 meters. As pressure goes down, this error goes down. So at very high altitude, where temperatures are low – error becomes less important. I will be more worried about LiPo battery, than about sensor.

Another changes

Changed way of displaying Actual altitude, and Maximum altitude reached, shown as A: and M: respectively. Both in feet and meters.

And got idea about barometric pressure (for altitude calculation), humidity and temperature of the base station. Later will be added another barometric sensor in the case of rapid change in weather, as is case past few days prior to rain. This second sensor together with humidity and temperature will make it almost complete meteorologic station, mobile one. Just missing wind speed, and few other parameters, but so far – it looks much better and more “rich” than before. 😀 To read meteo-data, just switch into second position, while altimeter continues to measure altitude and “remember” maximum reached. MaxAlt is done by simple code:

if (maxAltitude<=altitude) {maxAltitude=altitude;}

I wish to have better and bigger display in order to show all data at once instead changing “pages” on OLED, but here it is, what it is… New Nextion display ordered, just waiting to arrive.

First codes for TX, test phase

So far it works as a “Packet Radio” on 433 MHz, the ISM frequency. Transmitter and sensor + Attiny85 is chosen so that whole sending device will be under 3 grams – good for any vehicles. Unfortunately, it can’t work as altimeter not as vario + altimeter as planed. The main problem is in receiver side; if I combine relative slow transmission, some 24 packets maximum, tone sounds crazy and has delay. So, later version of the Arduino altimeter will has switch to chose altimeter or vario with the same circuit. For now, I did only altimeter, everything else will be added later (for those who found this page before end of test or beta phase of developing).

Some errors corrected

In the example below, initial idea is used from Arduino Vario by Rolf R. Bakke. He made initial code in such way that pressure is with OSR (OverSampling Ratio) for pressure, which is 4096 , so that resulting RMS (Root Mean Square) is 0.012 mBar (the lower number – the more precision). But (!), because higher OSR requires longer conversion inside MS5611 sensor chip, this value requires delay of 9.04 ms (minimum 7.40 ms, typical value is 8.22 ms and maximum value is 9.04 ms), So, for sake of ‘safety margins’, he uses 10 ms delay for pressure reading, since ADC need this time in OSR mode 4096. But, he uses OSR for temperature of just 256, which is equivalent of RMS of 0.012 °C, which is okay for vario, but not for altimeter – numbers jumping up and down too much. He probably made this decision because vario should be very fast, and already present delay of 10 ms + 1 ms at another command, adding more delay may result in too slow vario to be useful for sailplanes or gliders. The more samples per second – the faster the response.

Vario is one thing, altimeter another

For this reason, I changed call function from “D2 = getData(0x50, 1);” to “D2 = getData(0x58, 10);”, which has RMS of 0.002 °C – much better temperature correction data (six time better temperature correction than in the case of OSR 256, which gives RMS of 0.012 °C), but ten times longer to read (instead 1 ms, it needs over 9 ms to complete oversampling). The same as above for pressure, I am using 10 ms for good measure to prevent error(s). Anyone who want to experiment, try change from 10 ms to 1 – terrible error occur, instead some ‘reasonable’ pressure of say 1010 mbar, there is nonsense, something like -2.5 mbar. ADC converter just can’t cope with that speed, and reading sensor ends in big, really big error.

Why then in Attiny85 code is 1000 instead 10 ms?!

This is mystery to me. I had no time to investigate, but I suspect that library ‘VirtualWire’ resulting in such strange thing. It is actually good to have tens of microseconds (!) instead of thousands, or 1 ms (1000 µs = 1 ms). Since this strange thing is there, anyone who want to change some delay should multiply wanted value by factor of 100 to get proper delay in milliseconds. For example ‘delay(1000)’ usually means 1 second, but in example below, it will be delayed just 10 ms. So, for whole second, it should be ‘delay(100000)’. There is some limit, where delay can’t be set to high value, but instead should be used ‘for/to/next’ loop for more delay, if needed. For example 12 seconds: “for (i=1;i<=12;i++) {delay(100000)}”. This will be delay of 1 second repeated 12 times – 12 seconds. But, this is out of scope for this altimeter.

// Altimeter code by Milan Karakaš 2016
// Revision 2 - some precission errors corrected
// Revision 3 - added "second order temperature compensation",
// which corrects pressure error when temperature goes below 20°C.
// 315 MHZ or 433 MHz ASK (OOK) transmitter
// MS5611 sensor - just altimeter for now 
// Vehicle ID or just ID - set as you wish
// WARNING!!! delay 1000 ms -> delay 100000, 
// or two zerros to add, or multiply by 100
// don't know why it happens, so 1 ms should be
// writen as 100, not 1 as usually...
// Note that this is still beta version, need testing!

#include <TinyWireM.h>
#include <VirtualWire.h>
#include <Average.h>

#define n 4 //define number of average 
// the biger number n, the longer pause between two transmissions
Average<long>ave(n);
unsigned int calibrationData[7];
unsigned long time = 0;
long pressure, D1, D2, dT, P, Pa, TEMP, T2;
int ddsAcc, volt;
int64_t OFF, OFF2, SENS, SENS2;
byte data[7]; //number of data in array - 1 byte fir ID and 4 bytes for pressure
byte ID=0x2A; //"Vehicle ID" - set different value for each vehicle, also on RX side "myTX=0x2A"
float vref=5.07;

void setup()
{
 TinyWireM.begin(); //begins to comunicate with pressure sensor
 vw_set_tx_pin(1);  //set pin 4 (physical pin 3) on Attiny 85
 vw_setup(4800);    // Bits per sec
 setupSensor();     //call function for setup of the MS5611 sensor
// pinMode(4,INPUT);  //voltage measurement input
//vw_set_ptt_pin(3);  //depends of type of the transmitter 
                    //some no needs this, so use LED instead :)
                    //is is better to disable this pin, because
                    //some boards as is USB version of Attiny85
                    //uses this pins for something else
}

void loop()
{

for (int i=0;i<n;i++) //
  {
 getPressure();
 ave.push(P);
  }
Pa=(ave.mean()); //mean value of ave number (for example ave(10) is ten samples averaged)
volt=((analogRead(2)*vref)/1024)*100;

data[0]=ID;     //sending ID to array
data[1] = Pa;          //split long into first byte
data[2] = (Pa >> 8);   //split long into second byte
data[3] = (Pa >> 16);  //split long into third byte
data[4] = (Pa >> 24);  //split long into fourth and last byte
data[5] = volt;
data[6] = (volt >>8);

vw_send(data,7);       //now sending ID and four bytes to the receiver
vw_wait_tx();          //waiting until transmitter ends whole packet
delay(1000);// WARNING!!! delay 1000 ms -> delay 100000, two zerros add, or multiply by 100
/*This delay should be changed together with "Vehicle ID" in the case that multiple users 
 * fly at the same time to avoid overlaping and too much interferences. Receiver side has
 * CRC error checking, and in the case of interferences, it will just drop wrong packet and
 * continue listening until valid packet(s) is/are received. ID is single byte, and can be 
 * anything from 0 to 255 or in hexadecimal from 0x00 to 0xFF. In this case above of 1 mS 
 * delay, together with averaging of 4 samples from the MS5611 sensor, it gives 5 packets 
 * per second at 4800 bits per second. Sufficiently good for "normal" flight of quadcopter.
 */
}

//subfunction to get pressure
long getPressure()
{
//long D1, D2, dT, P, T2;
//long TEMP;
//int64_t OFF, SENS;

D1 = getData(0x48, 1000);
D2 = getData(0x58, 1000);

dT = D2 - ((long)calibrationData[5] << 8);
TEMP = (2000 + (((int64_t)dT * (int64_t)calibrationData[6]) >> 23)); //temperature before second order compensation
if (TEMP<2000)  //if temperature of the sensor goes below 20°C, it activates "second order temperature compensation"
{
  T2=pow(dT,2)/2147483648;
  OFF2=5*pow((TEMP-2000),2)/2;
  SENS2=5*pow((TEMP-2000),2)/4;
  if (TEMP<-1500) //if temperature of the sensor goes even lower, below -15°C, then additional math is utilized
  {
    OFF2=OFF2+7*pow((TEMP+1500),2);
    SENS2=SENS2+11*pow((TEMP+1500),2)/2;
  }
}
else 
{
T2=0;
OFF2=0;
SENS2=0;
}
TEMP = ((2000 + (((int64_t)dT * (int64_t)calibrationData[6]) >> 23))-T2); //second order compensation included
OFF = (((unsigned long)calibrationData[2] << 16) + (((int64_t)calibrationData[4] * dT) >> 7)-OFF2); //second order compensation included
SENS = (((unsigned long)calibrationData[1] << 15) + (((int64_t)calibrationData[3] * dT) >> 8)-SENS2); //second order compensation included
P = (((D1 * SENS) >> 21) - OFF) >> 15; 
return P; //returns back into main loop data about pressure P
}

long getData(byte command, int del) //function to getting data from the sensor
{
long result = 0;
twiSendCommand(0x77, command);
delay(del);
twiSendCommand(0x77, 0x00);
TinyWireM.requestFrom(0x77, 3);
if(TinyWireM.available()!=3);  // serial print je bio ovdje

for (int i = 0; i <= 2; i++)
{
result = (result<<8) | TinyWireM.read(); //read
}
return result;
}

//lets setup darn sensor :)
void setupSensor()
{

twiSendCommand(0x77, 0x1e);
delay(1000); //timing important - 1 ms = 1 ms * 100

for (byte i = 1; i <=6; i++)
{
unsigned int low, high;

twiSendCommand(0x77, 0xa0 + i * 2);
TinyWireM.requestFrom(0x77, 2);
if(TinyWireM.available()!=2);// Serial.println("Error: calibration data not available"); */
high = TinyWireM.read();
low = TinyWireM.read(); //read
calibrationData[i] = high<<8 | low;
}
}

//twi, whatsoever this means
void twiSendCommand(byte address, byte command)
{
  TinyWireM.beginTransmission(address);
  TinyWireM.write(command); //write
  TinyWireM.endTransmission();
}

 

Base station

Base station has OLED display for now, because found only this one. Later will consider make various options; OLED, TFT, numeric LCD, graphic LCD…

Just need time… First code for base station is here (sorry, no diagram yet, working whole night – for those who found this page in the meanwhile)

EDITED, forgot to assign Arduino Pin 9 and Pin 10 to the button and switch.

It is used later in program, but somehow forgot to set it in setup() function. It is ‘pinMode(9,INPUT);’ , as well as ‘pinMode(10,INPUT);’, also internal pull-up resistor ‘digitalWrite(9,HIGH);’ and ‘digitalWrite(10,HIGH);’  :

// Altimeter code by Milan Karakaš 2016
// Revision 2 - some precission errors corrected
// Revision 3 - sorted OLED screen; first screen showing Actual Altitude
// and Maximum reached Altitude, second screen showing barometric pressure
// Humidity and temperature sensors showing humidity and temperature on 
// the base station - very important is to know humidity, because every 
// flying object 'float' better when humidity is low (!)

#include <VirtualWire.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <DHT.h>

#define DHTPIN 2
#define DHTTYPE DHT22
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
#define degree_GLCD_HEIGHT 8
#define degree_GLCD_WIDTH 8
DHT dht(DHTPIN, DHTTYPE);
static const unsigned char PROGMEM degree_glcd_bmp[]=
{0x60, 0x90, 0x90, 0x60, 0x0,};
float altitude, maxAltitude,setpress,t,h;

uint8_t buf[7];
uint8_t buflen = 7;
long P;
byte ID, myTX=0x2A; //be sure that on your TX, the same ID "myTX is the same", here 0x2A hexacecmal
float volt;
float battOK=3.7; //minimum desired voltage for safe flight

void setup()
{
pinMode(9,INPUT); //this pin I forgot to include! Sorry people. 
digitalWrite(9,HIGH); //this one serves instead external 'pull-up' resistor - every time you have INPUT and provide HIGH to the output, it internally enable that resistor.
pinMode(10,INPUT); //also this one for switching display for various data sets.
digitalWrite(10,HIGH);//I think that one needs to, but actually this is switch, pin 10 goes to GND for one display option, or to +5V (or 3.3V) for another display option. Will turn pull-up resistor just in case.
display.begin(SSD1306_SWITCHCAPVCC, 0x3c);  // initialize with the I2C addr 0x3C (for the 128x32)
display.clearDisplay();
vw_set_rx_pin(7);
vw_setup(4800);
vw_rx_start();
dht.begin();
}

void loop()
{
  if (vw_get_message(buf,&buflen)) 
   {
     byte ID=buf[0];
   if (ID==myTX) 
   // if vehicle ID is wrong, it will just freeze last result, and do nothing
   // until "proper" connection is established, or proper ID is read - in the
   // case of more than one vehicle, each other will NOT listen (no 'crosstalk', 
   // so it will not showing wrong data - just vehicle which has proper ID
   {
     long P=((long)buf[1])+((long)buf[2]<<8)+((long)buf[3]<<16)+((long)buf[4]<<24);
     float volt=((buf[5])+(buf[6]<<8))/(float)100;
     if (volt<battOK) 
      {
      tone(3,800); 
      delay(50);
      noTone(3);
      }
     int line = (64-((volt-3.3)*71));
     altitude=145366.45*(1-pow(((P/(float)100)/(setpress/(float)100)),0.190284));
    
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius
  float t = dht.readTemperature();

     if (maxAltitude<=altitude) {maxAltitude=altitude;}

     if (digitalRead(9)==1)
      { delay(100);
      //by pressing button, Actual Altitude, and Maximum or Memorized Altitude
      //is set to zero as well
      //In the case of some major error, please press reset button on your Arduino
       setpress=P; 
       maxAltitude=altitude;
      }

     if (digitalRead(10)==1)
      {
        //write results, A: stands for Actual Altitude, 
        //M: stands for Maximum or Memorized Altitude
        display.clearDisplay();
        display.setTextSize(2);
        display.setTextColor(1);
        display.setCursor(0,0);
        display.print("A:");
        display.print(altitude,1);
        display.setCursor(0,16);
        display.setTextSize(2);
        display.print("A:");
        display.print(altitude*0.3048,1);
        display.setTextSize(2);
        display.setCursor(0,32);
        display.print("M:");
        display.println(maxAltitude,1);
        display.print("M:");
        display.print(maxAltitude*0.3048,1);
        //write designations as is feet and meters (ft, m)
        display.setTextSize(1);
        display.setCursor(113,3);
        display.println("ft");
        display.setCursor(118,19);
        display.setTextSize(1);
        display.print("m");
        display.setCursor(113,36);
        display.print("ft");
        display.setCursor(118,51);
        display.print("m");
        display.drawLine(127,64,127,line,1);
        display.display();
      }
      else 
      {
        //if switch is in different postion, show Actual Pressure,
        //humidity and temperature for weather station + battery status
        display.clearDisplay();
        display.setTextSize(2);
        display.setTextColor(1);
        display.setCursor(0,0);
        display.print("P:");
        display.print((float)P/100,2);
        display.setCursor(0,48);
        display.print("Bat: ");
        display.print((float)volt,2);

        display.setTextSize(2);
        display.setCursor(0,16);
        display.print("H:  ");
        display.println(h,2);
        display.print("T:  ");
        display.print(t,2);
        //lets make some symbols
        display.setTextSize(1);
        display.setCursor(108,03);
        display.println(" mb");
        display.setCursor(117,18);
        display.print("%");
        //Bitmap for symbol for degrees 
        display.drawBitmap(110,31,degree_glcd_bmp,8,8,1);
        display.setCursor(115,31);
        display.setTextSize(2);
        display.print("C");
        display.setCursor(115,48);
        display.print("V");
                display.setCursor(118,51);
        display.print("m");
        display.drawLine(127,64,127,line,1);
        display.display();
      }
   }
   // if this point is reached, probably ID is wrong, and it will back into loop again
   //else if (ID!=myTX) {tone(3,3000);delay(50);noTone(3);} 
   //do not apply code above - too loud, headache :D just leave it "open" to back into loop
   
   }

 }

 

The same MS5611 sensor is used in Arduino variometer. And it is cheaper than ever on Banggood.com

This is all for now

Come back soon, will be updated… Escpecially diagram and videos… Spring time requires hard work in my backyard, but also I did now and then some job for money, and this is main reason of delay of everything.

The ultimate WiFi antenna at 2.4 GHz

Good antenna? But, simple to build? YES!

Why bother with antenna?! Note that antennas are most important things for every transmission and reception. Aside use for quad-copters, airplanes and other flying bests, it works extremely well on WiFi Router/Client. On Router put “straight” or slightly angled dipole as is described on video as antenna for quad-copter, and for client – which may require some directionality – the “V” shape antenna is the best option.

The only difference which is not covered in this video is use of proper SMA connector. On quad and remote, I just soldered antennas at proper pins, while for WiFi – it is good to chose proper SMA or RP-SMA (Reverse Polarity SMA) connector, depend of where it is intended to use.

I strongly recommend use of RG316 coaxial cable, which is bit thicker than RG178, and has lower attenuation. It is your choice.

Which connector?

SMA Female Jack To RP-SMA Male Jack RF Coaxial Adapter Connector is the best, yet cheap connector for this purpose. Does not require crimping tools, but require patience and soldering iron. First solder center wire of the coax into hole, then put some glue to prevent short circuit. After glue (epoxy 2-component for example) cures, solder braided part of the coax all around. This way it is secured electrically and mechanically, while maintaining good properties of the antenna and low attenuation.

I can’t make ‘sleeve’ from braided part of the coaxial cable

I know. It is bit tricky and require patience. In the case of very thin cables, it is even more difficult. In this case, you may consider to do next trick: do everything as above, but instead moving inside-out braided part, leave 1-2 millimeters of this part so that additional part can be cut out from other piece of cable. Then move it from opposite end, until this 1-2 mm overlaps, then solder it carefully. This is maybe easier way to do this. Enjoy in such great antenna!

Tutorial: How to increase range of your toy-grade quadcopter and how to install buzzer.

Tutorial

Here is short Tutorial with video materials about how to increase range of toy-grade quadcopter as is for example Bayangtoys X8. It is not limited to his particular quadcopter, but may be applied to any other quadcopter as well. Plus, there is way to install buzzer – which may serve mainly two purposes: LVC (Low Voltage Controll), which sounds alarm when battery on quadcopter is low, and second – maybe most important thing, buzzer helps you to find lost quadcopter.

I think this one is better than old ‘cloverleaf’ antenna.

The case

Someone who followed this tutorial, and increased range of the drone:

But, then it happened

Nikola said: “After removing too heavy cover of the quad-copter, my flight was very long, but little bit unstable (without cover). But, there is no way back, just rising drone up to prevent treetops and begins to fly back, but then it happened:
Too small to be visible, just distant sound – but no more drone in sight. Trying to keep it in air for some time, but end result is… well, lost drone. Got to suspected crash location, wander for a while, but no much luck. Now, I know that I need buzzer… or perhaps GPS tracker.”

The other story, my personal

My first record was 550 meters, second one 800, and third one is 1100 meters. Or click to video below to watch whole video, or chose navigation times to watch exactly part you want. Don’t forget to share, comment, rate and subscribe to my YouTube channel if you found it useful. Thanks.

Navigation through this long video tutorial:
00:00 Antenna modification on remote
14:08 Antenna modification on drone
26:02 Installing buzzer for lost drone and battery alarm
37:31 Flying with modified antennas

Picture below showing how it looks when installed. If you click on the picture, you will get magnification. It opens in new tab.

Picture representing dimensions of wires and “sleeve” part.

On the transmitter (Remote), it looks different. While on receiver it is good to receive signal from every dirrection, on transmitter it is good to have somewhat directed signal:

Maximum radiation is in direction that arrow shows.

Note that according to math, center frequency of 2450 MHz (on 2.4 GHz band), Lambda is: 300/2450= 0.12245 m, or 122.45 mm. And then 1/4 lambda (1/4 wavelength) is then 122.45/4= 30.6 mm, but this working only for ultra-thin wire. As long as you have thicker wire, there is some so called “Shortening Factor“, similar to “Velocity Factor“. I am opened few WiFi antennas, and found that for this type of wires, it is about 29 mm, and “Sleeve” part, which serve as BALUN (Balanced-Unbalanced) is 26.4 mm (let’s round it to 26 mm).

This part serves important role in balancing RF signal from unbalanced (not “symmetric”) signal from coaxial cable into balanced 1/2 lambda dipole (very “symmetric”). All residual unbalanced RF signal goes over this 1/4 lambda sleeve and back over it to initial point, but now in proper phase so that bottom part of the dipole getting maximum possible signal.

Recommended coaxial cables for this antenna are: RG316 or thinner “cousin”: RG178. Thicker is better (less attenuation), but also this cable is heavier and can’t be bent easily if needed. My recommendation to use RG316 if possible. Both cables has PTFE (Teflon) insulation inside, which works great on high frequencies. Also, PTFE is heat resistant, so it is not easy to burn center of this cable by soldering iron. Only trouble is that this cable is though, not easy to cut, which is actually good in external application as is this antenna, but pain in the… to cut and manipulate. Yet, it is worth to mess with it, because it is very durable.

The reason why this antenna extending that far from the body of the Quadcopter is two fold: First and mostly important is put dipole as far as possible from noise sources (microcontroller, switching MOSFETs, motors), and second is odd multiplication of 1/4 lambda. Thus, maximum signal is feed to antenna with minimum SWR (Standing Wave Ratio). For both coaxial cables mentioned above, VF (Velocity Factor) is 0.7 or 70% of speed of light. This means that 1/4 lambda is 30.6 mm * 0.7 = 21.42 mm. This is first “odd multiplication”, or 1/4 * 1. Second one is 1/4  lambda * 3, where 21.42  * 3 = 64.26, or roughly 64 mm. Antenna is made from piece of coaxial cable 64 mm (3 * 1/4 lambda) + 29 mm (1/4 lambda dipole element).  Note that on opposite end of the dipole, you should to make cable so that can be soldered to the receiver board inside Quadcopter. Since you need about 5 mm for that, and then velocity factor and shortening factors changed slightly,  lets do it from 66+29= 95 mm. Cut coaxial cable exactly that long, then stripe insulation from 29 mm from one end, and 5 mm from another. Sleeve part may be done by removing braided wire and soldering 26 mm piece of braided wire from the same piece of coax, or from another one. Or, you may do it as is shown on following video:

Before complete whole tutorial, here is video of my record in range flight: 1100 meters with Bayangtoys X8 quadcopter, which had maximum range of 50-80 maybe maximum 100 meters. So, this is incresing range by tenfold!

For long ragne quadcopters, you need some FPV goggles.

Note that this video is on my second YouTube channel, completely dedicated for video and photo recordings from above, or aerial photo and video. You may subscrive on this channel too if you wish to enjoy my aerial videos. Thanks.

Compadre, did you forgot buzzer? Yes gringo, yes… I forgot it. But in the meanwhile, please take look at this beautiful nature from the above (thanks to extended range, I can fly very far):

Tutorial about installing buzzer

The buzzer is relatively easy to install. Sorry for hand drawing, I have no brain currently to search for some schematic program that can draw it nicely.

 

Note that I am using white LEDs, which has different properties than stock green and red LEDs. I found that for my setup, 27 kOhm is okay, but someone from RCGroups reported that in order to work properly, resistor should be down to 900 Ohms, or less. Please check it experimentally. This buzzer can save your lost quadcopter, and can indicate low battery, also known as LVC (Low Voltage Cutoff).

Note that it works only when LEDs are off, and it is silent while LEDs are on and glowing. If some quadcopter has button on remote that allow to switch off LEDs as is JJRC1000, then it can be done differently.:

On this quadcopter, if LEDs are off, buzzer is off as well, but when LVC begins to blink LEDs, buzzer also sounds with intermittent sound. Since, there is 5V voltage booster , no need for any additional electronic, just connect 5V buzzer +ve (positive) to cathode of the boost converter, and -ve (negative) wire of the buzzer to the MOSFET as is shown on this video.

Arduino Variometer

Notification for paragliders

Sorry for waiting that long. I found how to change Arduino code for paragliders. But I have no way to test it. If you need that for your paraglider or whatever flying thing, please leave me comment below. We need first test it, so that I can be sure that it works, then will upload this post. Thanks. Sensitivity can be changed in next line (original value is 50). line 31:

toneFreq = (lowpassSlow – lowpassFast) * 10;

The main part is with silencing vario when no much ressure/altitude change (now it is silent between certain points, experiment with those values -50 and 50, maybe -30/30, or -70/70, this is how much frequency will change with pressure change in time):
line 39:

if (toneFreq < -50 || toneFreq > 50 && ddsAcc >0 )

Sorry, previous change on this web page was wrong for same reason. This one should work. I am not sure what happened, perhaps forgot to update.

Please notify me after you confirm that it is useful for paragliders.

Continue reading Arduino Variometer

About me

You are about to read who I am: Milan Karakaš from Croatia.

For those who are not familiar with Croatian letters, just Milan Karakas. Doesn’t matter how you pronounce this letter.  Born in Croatia, year 1962, in relative small town Vinkovci, and still live there. I am electrician by my education, but my hobbies gives me insight into many other things, such as electronic, flying RC airplanes and quad-copters, and many more.

Eccentric?!

Maybe. Some people see me as eccentric, and maybe I am. Almost all my life I am trying to be ‘normal’, whatsoever this means. But, someone told me honestly that I am little bit eccentric, so after some thinking, I gave up of trying to be ‘normal’ by any definition. I am who I am, I can’t change anything about me and my life. In the same time, I am not forcing to show to people that I am eccentric, but also did not hesitate to do many eccentric things.

Why no high-er education then?!

Well. At first, I was very intimidated by amount of learning in short time to get some diploma. And it may cost a lot, not only in $$, but also frustration and related things. Good period of my life wondering whether I should to go to some high school, but always got the same conclusion: diploma is just a paper, real learning actually never stops. Especially today, when internet is present, which was not so in my growing phases. Anyone who want to know more, there is plenty of things to learn over the internet. Maybe more than good old way of reading books. I read many books about physics, optics, lasers, radio and electronic, but all of that is just some foundation for continuation of learning over the internet.

Job? Employment?

I worked as electrician for one year, then change job and worked in Ministry of defence. After war in Croatia, my father opened Accountancy/Bookkeeping, and changed job again. In the meanwhile opened my own business as a professional photographer, but this job did not last long – in year 2004 got heart attack, and almost died. Since then, my mental and physical health begins to degrade, and very soon I got retirement. Simply, I can’t work more than one or two hours in continuation. I wish to write more about my life, but right now feel bad about all of that, so maybe latter…

Plans for the future

So far, as situation developing, no bright future, nor fixed plans. I am trying to share my accumulated knowledge with others, mainly over my YouTube channel(s), and now on this website. but it is not always easy. It is not just about common knowledge, but some peculiar findings that make many things interesting. That is why I call it wild.

Thank you for visiting my wild website.