PWM and logarithmic function

Basically I am controling a ampere metre. I am using an transistor (came with Uno Starter kit) to charge a capacitator, that capacitator is emptied trough large resistors trough the apere metre. The problem is that the arduino PWM library was too low resolution and always managed to fully charge the capacitator instantly. I am using code down below.

The ampere metre goes from 0% to 100% with a values of 0 until 4300. But if I linearily increase a value the aperemetre value grows logarithmically, the map function did not help other than reducing the resolution.

So I've got two problems: 1) How to control the ampere metre dial with linear scale instead of logarithmic?

2) How to "background" the process of charging the capacitator, like Arduino's PWM function? Currently any other code throws the dial to 0.

digitalWrite(led, HIGH);
  if (a > 0) {  
    delayMicroseconds(a);
    digitalWrite(led, LOW);
    delayMicroseconds(10000 - a);
  }

As English is not my first language I really hope I was clear enough, if anything is unclear, please let me know.

Please describe the external circuitry: resistors, capacitors, resistance of the meter movement and the full scale meter current.

jremington: Please describe the external circuitry: resistors, capacitors, resistance of the meter movement and the full scale meter current.

Arduino Nano is switching an BC547B trough a 220 ohm resistor. E on the transistor is connected to ground, C is connected to the ampere metre trough 2*1Kohm and one 2Kohm resistor in parallel. The C is also connected to a 2200uF 6.3V cap to the 5V. Meter goes from 0mA to 10mA, it is an old analogue one. The meters internal resistance is 8.4 ohms.

This circuit most likely is not the right one, but this was all I could come up with as an beginner. If you can suggest me something better, let me know.

Hi,

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Can you please post a copy of your complete sketch, using code tags?
They are made with the </> icon in the reply Menu.
See section 7 http://forum.arduino.cc/index.php/topic,148850.0.html

Thanks …Tom… :slight_smile:

TomGeorge:
Hi,

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Can you please post a copy of your complete sketch, using code tags?
They are made with the </> icon in the reply Menu.
See section 7 http://forum.arduino.cc/index.php/topic,148850.0.html

Thanks …Tom… :slight_smile:

int led = 6;           // the pin that the LED is attached to
int a = 3000;
// the setup routine runs once when you press reset:
void setup() {
  // declare pin 9 to be an output:
  pinMode(led, OUTPUT);
  Serial.begin(115200);
}

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);
  if (a > 0) {
    digitalWrite(led, LOW);
    delayMicroseconds(a);
    delayMicroseconds(10000 - a);
  }
}

This is the code, just as in the first post.

|500x386 The schematic, altho it does not matter much. My questions are software related.

10 mA (full scale meter deflection) is OK for the port pin to supply directly, so try something like the attached simple RC filter. The current through the meter is linearly proportional to the average voltage, hence linearly to the PWM on time. The circuit has a response time to changes in the PWM value of about 0.1 seconds.

meter.gif

Avamander: ... But if I linearily increase a value the aperemetre value grows logarithmically, the map function did not help other than reducing the resolution....

You could use multimap() for non linear mapping - http://playground.arduino.cc/Main/MultiMap -

I don't think logs are going to help you since you never change the value of a.

DVDdoug: I don't think logs are going to help you since you never change the value of a.

Yeah, I think I am never gonna change the value of the variable called "a" I like it the way it is.

Avamander:

The schematic, although it does not matter much. My questions are software related.

I think that you are wrong to assume that it is a software problem.

I’m sure that it is the capacitor causing the problem.

It will charge up quickly from the PWM pulses, but will take much longer to discharge through the resistors and meter. (The time constant of the capacitor and the resistors is around 800ms.)

I think you need to remove the capacitor completely, or connect it in a different position.

If it was just connected across the meter, then it would filter the PWM signal, and give a more linear response.

I rearranged the circuit as the schematic shows and it now works, exept when the direction changes it jumps to the opposite end for a moment. During any other value it moves smoothly.

int ampere = 6;
unsigned long int last;
bool directionn;
int value = 1;
void setup() {
  // declare pin 9 to be an output:
  pinMode(ampere, OUTPUT);
  Serial.begin(115200);
}

void loop() {
  analogWrite(ampere, value);
  if (millis() - last > 250) {
    if (directionn == 1) {
      value++;
    } else {
      value--;
    }
    if (value > 255) {
      directionn = 0;
    } else if (value < 0) {
      directionn = 1;
    }
    Serial.println(value);
    last = millis();
  }
}

You don't need the transistor.

Yep, I removed it.

Valid values for analogWrite() are 0 to 255.

You are not changing direction until you go outside that range.
It is no surprise that it jumps when you send illegal values to the analogWrite() function

try changing:

if (value > 255) {
      directionn = 0;
    } else if (value < 0) {
      directionn = 1;

to:

if (value > 254) {
      directionn = 0;
    } else if (value < 1) {
      directionn = 1;

JohnLincoln:
Valid values for analogWrite() are 0 to 255.

You are not changing direction until you go outside that range.
It is no surprise that it jumps when you send illegal values to the analogWrite() function

try changing:

if (value > 255) {

directionn = 0;
    } else if (value < 0) {
      directionn = 1;



to:


if (value > 254) {
      directionn = 0;
    } else if (value < 1) {
      directionn = 1;

Many thanks!