Use Arduino Yun code on my Arduino Uno

Hello everyone,

I am a student in France planning to do an experiment with an Arduino Uno.
I would like to measure the voltage and intensity delivered by a battery during 24 hours.
The problem is that the code I have found for that has been conceived for an Arduino Yun. And I don't have one.
It uses the SD port and the timer3 of the Yun.

The arduino would store data on the SD card. Since the Uno can't have one, I used the Keyboard.h library to write data directly in a file on my computer.
But I am stuck with the timer3 problem.

I am not a Arduino professional, but I understood that the Arduino Uno only have timer0, timer1 and timer2.
I would like to be able to use those instead of the timer3 of the original code.

Here is my modified code with the keyboard library changes, and below is the original one.
I tried to translate the variables so that it is easier for you guys to understand it.

My modified code
#include "Arduino.h"
#include <Keyboard.h>

#define OUT 7
#define VREF 1.82


uint16_t divider[6] = {0,1,8,64,256,1024};

float resistance = 10.6;
volatile float x[2];
float current;
float charge,voltage,emf; //emf stands for electro-motive force
float u0,u1;
volatile int counter = 0;
float te;
String data;
volatile int flag;
float time = 0;
            
//The function below set up the timer3 for periodic interruptions
void timer3_init(uint32_t period) {
    TCCR3A = (1 << COM3A1) | (1 << COM3A0);
    TCCR3B = (1 << WGM33);
    uint32_t top = (F_CPU/1000000*period/2);
    int clock = 1;
    while ((top>0xFFFF)&&(clock<5)) {
          clock++;
          top = (F_CPU/1000000*period/2/divider[clock]);
      }
    ICR3 = top;
    TIMSK3 = 1 << TOIE3;
    TCCR3B |= clock;
}
             
//The function below is called for each interruption (every second)
ISR(TIMER3_OVF_vect) {
    time += te;
    counter++;
    if (counter==60) {
      counter = 0;
      digitalWrite(OUT,LOW);  // transistor blocked
      delay(100);
      emf = analogRead(0)*VREF/1024;
      digitalWrite(OUT,HIGH); // transistor saturated
      data = String(time)+"\t"+String(emf)+"\t"+String(voltage)+"\t"+String(current)+"\t"+String(charge);
      current = 0;
      flag = 1;
    }
    else  {
      u0 = analogRead(0)*VREF/1024;
      u1 = analogRead(1)*VREF/1024;
      voltage = u0;
      current = (u0-u1)/resistance;
    }
    // Integration of the current to get the charge
    x[1] = x[0];
    x[0] = current;
    charge += te*0.5*(x[0]+x[1]);
}
              
void setup() {
  pinMode(OUT,OUTPUT);
  digitalWrite(OUT,HIGH);
  analogReference(EXTERNAL);
  te = 1.0; // one second
  charge = 0.0;
  x[0] = x[1] = 0;
  flag = 0;
  timer3_init(te*1000000);
}
              
void loop() {
    if (flag) {
        Keyboard.begin();
        Keyboard.println(data);
        Keyboard.end();
        flag = 0;
      }
  }
}
               
The original code
#include "Arduino.h"
#include <FileIO.h> //I removed this library, used for televersing data into the SD card, and added the keyboard library

#define OUT 7
#define VREF 1.82


uint16_t divider[6] = {0,1,8,64,256,1024};

float resistance = 10.6;
volatile float x[2];
float current;
float charge,voltage,emf; //emf stands for electro-motive force
float u0,u1;
volatile int counter = 0;
float te;
String data;
volatile int flag;
float temps = 0;
            
//The function below set up the timer3 for periodic interruptions
void timer3_init(uint32_t period) {
    TCCR3A = (1 << COM3A1) | (1 << COM3A0);
    TCCR3B = (1 << WGM33);
    uint32_t top = (F_CPU/1000000*period/2);
    int clock = 1;
    while ((top>0xFFFF)&&(clock<5)) {
          clock++;
          top = (F_CPU/1000000*period/2/divider[clock]);
      }
    ICR3 = top;
    TIMSK3 = 1 << TOIE3;
    TCCR3B |= clock;
}
             
//The function below is called for each interruption (every second)
ISR(TIMER3_OVF_vect) {
    time += te;
    counter++;
    if (counter==60) {
      counter = 0;
      digitalWrite(OUT,LOW);  // transistor blocked
      delay(100);
      emf = analogRead(0)*VREF/1024;
      digitalWrite(OUT,HIGH); // transistor saturated
      data = String(time)+"\t"+String(emf)+"\t"+String(voltage)+"\t"+String(current)+"\t"+String(charge);
      current = 0;
      flag = 1;
    }
    else  {
      u0 = analogRead(0)*VREF/1024;
      u1 = analogRead(1)*VREF/1024;
      voltage = u0;
      current = (u0-u1)/resistance;
    }
    // Integration of the current to get the charge
    x[1] = x[0];
    x[0] = current;
    charge += te*0.5*(x[0]+x[1]);
}
              
void setup() {
  pinMode(OUT,OUTPUT);
  digitalWrite(OUT,HIGH);
  analogReference(EXTERNAL);
  Bridge.begin(); //Those three lines have been deleted in my modified code
  FileSystem.begin();
  FileSystem.remove("/mnt/sd/alcaline.txt");
  te = 1.0; // one second
  charge = 0.0;
  x[0] = x[1] = 0;
  flag = 0;
  timer3_init(te*1000000);
}
              
void loop() {
    if (flag) {
      File dataFile = FileSystem.open("/mnt/sd/alcaline.txt", FILE_APPEND);
      if (dataFile) {
        dataFile.println(data);
        dataFile.close();
        flag = 0;
      }
  }
}
        
Image of the electrical assembly

Source of the original code

Décharge pile

I am not asking for a miracle solution, but just a little insight on how I could replace the timer3 with something else that is integrated on the Uno card.
I am available for any question about the code.

Thank you in advance,
ElTran.

Could You please post Your modified code here, formatted and using code tags?
Posting the drawing would also be wellcome. No Oc available for the moment...

It's not a good idea to port controller specific code to another controller. You better find out what the code means and then implement it on the target machine. Taking readings in regular time intervals and integration is not rocket science, it can be implemented in the smallest controller.

The String data type is unusable on small controllers like an Uno for memory (SRAM) fragmentation.

For the SD card you can either use a shield on the Uno or some other board with integrated SD card.

1 Like

I followed your suggestion to re-start the code from scratch and it worked!
Thank you!

Understanding how it works really was the best way to solve this problem.

My keyboard solution wouldn't work with a Uno. So I instead send my data to the serial monitor. Then a software called CoolTerm print those data into a .txt file. My PC need to stay ON during all of the experiment but that isn't really a problem.
As for the timer issue, I used a simple delay(1000) at the end of my loop, and re-wrote the code so that it would work the way I want it to.

Thank you again for your solution, which in fact was the most obvious one.

1 Like