Для экспонометра на основе Arduino Sketch функции вне «петли» не отключаются / не работают - PullRequest
0 голосов
/ 12 марта 2012

Я очень новичок в Arduino. У меня гораздо больше опыта работы с Java и ActionScript 3. Я работаю над созданием экспонометра из Arduino Uno и TAOS TSL235R преобразователя света в частоту.

Я могу найти учебник только с использованием другого датчика, так что я работаю над тем, чтобы преобразовать то, что мне нужно, чтобы все это заработало (AKA немного копирует и вставляет, стыдно, но я новичок в этом).

Три части: это первое руководство из серии Arduino и датчик света Taos TSL230R: начало работы .

Фотографическое преобразование: Arduino и TSL230R: Фотографическое преобразование .

Сначала я мог возвращать значения для частоты, созданной датчиком TSL235R, но как только я попытался добавить код для фотографических преобразований, я получил только возвращенный ноль, и ни одна из функций вне основного цикла, похоже, не срабатывает что мой Serial.Println() ничего не возвращает.

Меня больше волнует создание функций, чем если бы моя математика была идеальной. В ActionScript и Java есть прослушиватели событий для функций и тому подобное, нужно ли мне объявить функцию для ее запуска в C / C ++?

В общем, как я могу сделать так, чтобы все мои функции запускались на языке программирования C?

Мой Arduino Эскиз :

// TSL230R Pin Definitions
#define TSL_FREQ_PIN 2

// Our pulse counter for our interrupt
unsigned long pulse_cnt = 0;

// How often to calculate frequency
// 1000 ms = 1 second
#define READ_TM 1000

// Two variables used to track time
unsigned long cur_tm = millis();
unsigned long pre_tm = cur_tm;

// We'll need to access the amount of time passed
unsigned int tm_diff = 0;

unsigned long frequency;
unsigned long freq;
float lux;
float Bv;
float Sv;
// Set our frequency multiplier to a default of 1
// which maps to output frequency scaling of 100x.
int freq_mult = 100;

// We need to measure what to divide the frequency by:
//   1x sensitivity =   10,
//  10x sensitivity =  100,
// 100x sensitivity = 1000
int calc_sensitivity = 10;


void setup() {
    attachInterrupt(0, add_pulse, RISING);  // Attach interrupt to pin2.
    pinMode(TSL_FREQ_PIN, INPUT); //Send output pin to Arduino
    Serial.begin(9600);  //Start the serial connection with the copmuter.
}//setup


void loop(){
    // Check the value of the light sensor every READ_TM ms and
    // calculate how much time has passed.
    pre_tm   = cur_tm;
    cur_tm   = millis();

    if( cur_tm > pre_tm ) {
        tm_diff += cur_tm - pre_tm;
    }
    else
        if( cur_tm < pre_tm ) {
            // Handle overflow and rollover (Arduino 011)
            tm_diff += ( cur_tm + ( 34359737 - pre_tm ));
        }

    // If enough time has passed to do a new reading...
    if (tm_diff >= READ_TM ) {
        // Reset the ms counter
        tm_diff = 0;

        // Get our current frequency reading
        frequency = get_tsl_freq();

        // Calculate radiant energy
        float uw_cm2 = calc_uwatt_cm2( frequency );

        // Calculate illuminance
        float lux = calc_lux_single( uw_cm2, 0.175 );
    }
    Serial.println(freq);
    delay(1000);
} //Loop


unsigned long  get_tsl_freq() {
    // We have to scale out the frequency --
    // Scaling on the TSL230R requires us to multiply by a factor
    // to get actual frequency.
    unsigned long freq = pulse_cnt * 100;
    // Reset pulse counter
    pulse_cnt = 0;
    return(freq);
    Serial.println("freq");
} //get_tsl_freq


void add_pulse() {
   // Increase pulse count
   pulse_cnt++;
   return;
   Serial.println("Pulse");
}//pulse


float calc_lux_single(float uw_cm2, float efficiency) {
    // Calculate lux (lm/m^2), using standard formula
    //     Xv = Xl * V(l) * Km

    // where Xl is W/m^2 (calculate actual received uW/cm^2, extrapolate from sensor size
    // to whole cm size, then convert uW to W),
    // V(l) = efficiency function (provided via argument) and
    // Km = constant, lm/W @ 555 nm = 683 (555 nm has efficiency function of nearly 1.0).
    //
    // Only a single wavelength is calculated - you'd better make sure that your
    // source is of a single wavelength...  Otherwise, you should be using
    // calc_lux_gauss() for multiple wavelengths.

    // Convert to w_m2
    float w_m2 = (uw_cm2 / (float) 1000000) * (float) 100;
    // Calculate lux
    float lux  = w_m2 * efficiency * (float) 683;
    return(lux);
    Serial.println("Get lux");
} //lux_single


float calc_uwatt_cm2(unsigned long freq) {
    // Get uW observed - assume 640 nm wavelength.
    // Note the divide-by factor of ten -
    // maps to a sensitivity of 1x.
    float uw_cm2 = (float) freq / (float) 10;
    // Extrapolate into the entire cm2 area
    uw_cm2 *= ( (float) 1 / (float) 0.0136 );
    return(uw_cm2);
    Serial.println("Get uw_cm2");
} //calc_uwatt


float calc_ev( float lux, int iso ) {
    // Calculate EV using the APEX method:
    //
    // Ev = Av + Tv = Bv + Sv
    //
    // We'll use the right-hand side for this operation:
    //
    // Bv = log2( B/NK )
    // Sv = log2( NSx )

    float Sv = log( (float) 0.3 * (float) iso ) / log(2);

    float Bv = log( lux / ( (float) 0.3 * (float) 14 ) ) / log(2);

    return( Bv + Sv );
    Serial.println("get Bv+Sv");
}


float calc_exp_tm ( float ev, float aperture  ) {
    // Ev = Av + Tv = Bv + Sv
    // need to determine Tv value, so Ev - Av = Tv
    // Av = log2(Aperture^2)
    // Tv = log2( 1/T ) = log2(T) = 2^(Ev - Av)

    float exp_tm = ev - ( log( pow(aperture, 2) ) / log(2) );

    float exp_log = pow(2, exp_tm);

    return( exp_log  );
    Serial.println("get exp_log");
}


unsigned int calc_exp_ms( float exp_tm ) {
    unsigned int cur_exp_tm = 0;

    // Calculate mS of exposure, given a divisor exposure time.

    if (exp_tm >= 2 ) {
        // Deal with times less than or equal to half a second

        if (exp_tm >= (float) int(exp_tm) + (float) 0.5 ) {
            // Round up
            exp_tm = int(exp_tm) + 1;
        }
        else {
            // Round down
            exp_tm = int(exp_tm);
        }
        cur_exp_tm = 1000 / exp_tm;
    }
    else if( exp_tm >= 1 ) {
        // Deal with times larger than 1/2 second

        float disp_v = 1 / exp_tm;
        // Get first significant digit
        disp_v       = int( disp_v * 10 );
        cur_exp_tm = ( 1000 * disp_v ) / 10;
    }
    else {
       // Times larger than 1 second
       int disp_v = int( (float) 1 / exp_tm);
       cur_exp_tm = 1000 * disp_v;
    }
    return(cur_exp_tm);
    Serial.println("get cur_exp_tm");
}


float calc_exp_aperture( float ev, float exp_tm ) {
    float exp_apt = ev - ( log( (float) 1 / exp_tm ) / log(2) );
    float apt_log = pow(2, exp_apt);

    return( apt_log );
    Serial.println("get apt_log");
}

1 Ответ

2 голосов
/ 12 марта 2012

Это большой код для чтения, с чего мне начать.

В вашем loop() вы присваиваете frequency, но печатаете freq

// get our current frequency reading  
   frequency = get_tsl_freq();  
-- snip --
Serial.println(freq);

in get_tsl_freq() вы создаете локальный unsigned int freq, который скрывает глобальный freq, и используете его для вычисления и возврата значения, возможно, это также является источником путаницы для вас.Я не вижу причин для того, чтобы frequency и freq были глобальными в этом коде.Функция также содержит недостижимый код, элемент управления оставит функцию при возврате, операторы после возврата никогда не будут выполнены.

unsigned long  get_tsl_freq() {  
    unsigned long freq = pulse_cnt * 100;  <-- hides global variable freq  
    // re-set pulse counter  
    pulse_cnt = 0;   
    return(freq);           <-- ( ) not needed
    Serial.println("freq"); <-- Unreachable
}

Читая немного больше, я могу предложить вам взять книгу по С ++ и прочитатьнемного.В то время как ваш код компилируется, он не является технически допустимым C ++, но вам это сходит с рук благодаря программному обеспечению Arduino, которое выполняет некоторые искажения и не позволяет использовать функции до их объявления.

Для констант, которые вы используете в своих вычислениях

float w_m2 = (uw_cm2 / (float) 1000000) * (float) 100; 

можно записать как

float w_m2 = (uw_cm2 / 1000000.0f) * 100.0f; 

или даже так, потому что uw_cm2 - это число с плавающей точкой

float w_m2 = (uw_cm2 / 1000000) * 100;

Вы также, кажется, используете оба подхода кожидание, у вас есть код, который вычисляет и запускает, только если он был больше 1000 мс с момента последнего запуска, но затем вы также delay(1000) в том же коде, это может работать совсем не так, как ожидалось.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...