Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » Измерение переменного тока с ACS712


Измерение переменного тока с ACS712

Сообщений 1 страница 2 из 2

1

Приветствую! Пытаюсь измерить переменный ток с помощью датчика ACS712. Нашел код для ардуино на http://geektimes.ru/post/258384/ Под ардуино все работает, попытался переписать под BascomAVR, но не получилось. Прошу помощи с поиском ошибок.

Код для ардуино

Код:
#include <math.h>

String inputString = "";
boolean stringComplete = false;
boolean badInput = false;
const int pins[] = {A0,A1,A2,A3};
const int FREQUENCY = 50; // Hz
//const double ADC_SCALE = 1024 / 5 * 0.185; //ACS712 (0.066-0.185)
const double ADC_SCALE = 1024 / 5 * 0.1; // ACS758 (0.4)

int data[128];

void setup() {
  Serial.begin(9600);
  inputString.reserve(16);
}

void loop() {
  // process command
  if (badInput) {
    Serial.println("Error 1: Invalid command: " + inputString);
    resetInput();
  } else if (stringComplete) {
    if (inputString.length() < 2) {
      Serial.println("Error 1: Invalid command: " + inputString);
      resetInput();
    } else {
      unsigned int pin = inputString.charAt(0) - '0';
      if (pin > sizeof(pins) / sizeof(int)) {
        Serial.println("Error 2: Bad pin: " + inputString);
      } else {
        unsigned int cmd = inputString.charAt(1) - '0';
        unsigned long t1, t2;
        double currentMax;
        switch(cmd) {
          case 0:
            // Report current
            t1 = micros();
            for (int i=0; i < sizeof(data) / sizeof(int); i++) {
              data[i] = analogRead(pins[pin]);
            }
            t2 = micros();
            // Overhead to measure time is only 100 us; each cycel is 112 us
            // The error is less than 0.2 percent. Can safely ignore it :)
            currentMax = calcADC( 2 * M_PI * (t2 - t1) * FREQUENCY / 1000000 / (sizeof(data) / sizeof(int)) );
            
            Serial.println( currentMax / ADC_SCALE / M_SQRT2 );
            break;
          case 1:
            // Turn on relay
            Serial.println("Error 3: Not implemented: " + inputString);
            break;
          case 2:
            // Turn off relay
            Serial.println("Error 3: Not implemented: " + inputString);
            break;
          default:
            Serial.println("Error 1: Invalid command: " + inputString);
        }
      }
    }
    resetInput();
  }
}

void serialEvent() {
  while (Serial.available()) {
    char ch = (char)Serial.read();
    if (stringComplete) {
      continue; // Ignore any input while previous pending processing
    }
    if (ch == '\n') {
      stringComplete = true;
    } else if (inputString.length() >= 16) {
      badInput = true;
    } else {
      inputString += ch;
    }
  }
}

void resetInput() {
  inputString = "";
  stringComplete = badInput = false;
}

double calcADC(double angularVelocity) {
  size_t n = sizeof(data) / sizeof(int);
  double N  = (double)n;
  double X  = 0;
  double Y  = 0;
  double Z  = 0;
  double X2 = 0;
  double Y2 = 0;
  double XY = 0;
  double XZ = 0;
  double YZ = 0;

  for (int i = 0; i < n; i++)
  {
    double sine   = sin(angularVelocity * i);
    double cosine = cos(angularVelocity * i);
    X  += sine;
    Y  += cosine;
    Z  += data[i];
    X2 += sine*sine;
    Y2 += cosine*cosine;
    XY += sine*cosine;
    XZ += sine*data[i];
    YZ += cosine*data[i];
  }

  //double a0 = det3x3(Z, X, Y,XZ, X2, XY, YZ, XY, Y2) / det3x3(N, X, Y, X, X2, XY, Y, XY, Y2);
  double a1 = det3x3(N, Z, Y, X, XZ, XY, Y, YZ, Y2) / det3x3(N, X, Y, X, X2, XY, Y, XY, Y2);
  double a2 = det3x3(N, X, Z, X, X2, XZ, Y, XY, YZ) / det3x3(N, X, Y, X, X2, XY, Y, XY, Y2);

  return sqrt(a1*a1 + a2*a2);
}

double det3x3(
  double m00, double m01, double m02,
  double m10, double m11, double m12,
  double m20, double m21, double m22
){
  return m00*m11*m22 + m01*m12*m20 + m10*m21*m02 - m02*m11*m20 - m01*m10*m22 - m00*m12*m21;
}

Моя попытка

Код:
$regfile = "m168pdef.dat"
$crystal = 11059200
$baud = 9600
$swstack = 128
$hwstack = 128
$framesize = 128

Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc

Config Timer1 = Timer , Prescale = 64
On Timer1 Micros
Enable Interrupts
Enable Timer1
Start Timer1

Const Freq = 50
'const double ADC_SCALE = 1024 / 5 * 0.185
Const Adc_scale = 37.888

Dim Adc_in As Word
Dim Data_array(128) As Word
Dim I As Word

Dim T1 As Long
Dim T2 As Long

Dim Current_max As Single

Dim N As Single
Dim X As Single
Dim Y As Single
Dim Z As Single
Dim X2 As Single
Dim Y2 As Single
Dim Xy As Single
Dim Xz As Single
Dim Yz As Single

Dim Sine As Single
Dim Cosine As Single

Dim Det As Single
Dim Det_1 As Single
Dim Det_2 As Single
Dim Det_3 As Single
Dim Det_4 As Single

Dim A1 As Single
Dim A2 As Single

Dim A As Single
Dim B As Single

Dim Micr As Long
Micr = 0

Dim Temp_x2 As Single
Dim Temp_y2  as Single
Dim Temp_xy  as Single
Dim Temp_xz   as Single
Dim Temp_yz As Single

Declare Sub Deter(m00 As Single , M01 As Single , M02 As Single , M10 As Single , M11 As Single , M12 As Single , M20 As Single , M21 As Single , M22 As Single)

Do
T1 = Micr
'read ADC values
For I = 0 To 128 Step 1
Adc_in = Getadc(3)
Data_array(i) = Adc_in
Print I ; ":" ; Data_array(i)
Next
T2 = Micr

For I = 0 To 128 Step 1
B = I
Sine = Sin(b)
Cosine = Cos(b)
N = 128.00
X = X + Sine
Y = Y + Cosine
Z = Z + Data_array(i)
Temp_x2 = Sine * Sine
X2 = X2 + Temp_x2
Temp_y2 = Cosine * Cosine
Y2 = Y2 + Temp_y2
Temp_xy = Sine * Cosine
Xy = Xy + Temp_xy
Temp_Xz = Sine * Data_array(i)
Xz = Xz + Temp_Xz
Temp_Yz = Cosine * Data_array(i)
Yz = Yz + Temp_Yz
Next

'Single a1 = det3x3(N, Z, Y, X, XZ, XY, Y, YZ, Y2) / det3x3(N, X, Y, X, X2, XY, Y, XY, Y2);
'Single a2 = det3x3(N, X, Z, X, X2, XZ, Y, XY, YZ) / det3x3(N, X, Y, X, X2, XY, Y, XY, Y2);

Call Deter(n , Z , Y , X , Xz , Xy , Y , Yz , Y2)
Det_1 = Det
Call Deter(n , X , Y , X , X2 , Xy , Y , Xy , Y2)
Det_2 = Det
Call Deter(n , X , Z , X , X2 , Xz , Y , Xy , Yz)
Det_3 = Det
Call Deter(n , X , Y , X , X2 , Xy , Y , Xy , Y2)
Det_4 = Det

A1 = Det_1 / Det_2
A1 = A1 * A1
A2 = Det_3 / Det_4
A2 = A2 * A2

A = A1 + A2
A = Sqr(a)

'currentMax = calcADC( 2 * M_PI * (t2 - t1) * FREQUENCY / 1000000 / (sizeof(data) / sizeof(int)) );

Current_max = T2 - T1
Current_max = Current_max * 6.28
Current_max = Current_max * Freq
Current_max = Current_max / 1000000
Current_max = Current_max / 128
Current_max = Current_max * A
Current_max = Current_max / Adc_scale
Current_max = Current_max / 1.414

Print Det_1
Print Det_2
Print Det_3
Print Det_4

Print T1
Print T2

Print Current_max

Wait 1
Loop
End

Sub Deter(m00 As Single , M01 As Single , M02 As Single , M10 As Single , M11 As Single , M12 As Single , M20 As Single , M21 As Single , M22 As Single)
'return m00*m11*m22 + m01*m12*m20 + m10*m21*m02 - m02*m11*m20 - m01*m10*m22 - m00*m12*m21;
Local Temp_1 As Single
Local Temp_2 As Single
Local Temp_3 As Single
Local Temp_4 As Single
Local Temp_5 As Single
Local Temp_6 As Single

Temp_1 = M00 * M11
Temp_1 = Temp_1 * M22

Temp_2 = M01 * M12
Temp_2 = Temp_2 * M20

Temp_3 = M10 * M21
Temp_3 = Temp_3 * 02

Temp_4 = M02 * M11
Temp_4 = Temp_4 * M20

Temp_5 = M01 * M10
Temp_5 = Temp_5 * M22

Temp_6 = M00 * M12
Temp_6 = Temp_6 * M21

Det = Temp_1 + Temp_2
Det = Det + Temp_3
Det = Det - Temp_4
Det = Det - Temp_5
Det = Det - Temp_6

End Sub

Micros:
Incr Micr
Return

0

2

Посмотрите здесь

0


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » Измерение переменного тока с ACS712