arduino mảng

Để truyền đối số mảng cho một hàm, hãy chỉ định tên của mảng mà không có bất kỳ dấu ngoặc nào. Ví dụ, nếu một mảng giờ đã được khai báo là hàm, thì lệnh gọi sẽ chuyển mảng giờ hàng ngày và kích thước của nó sang hàm modArray .

Điểm quan trọng

Dưới đây là danh sách một số điểm quan trọng mà bạn cần biết khi chuyển mảng cho các hàm:

  • Khi truyền một mảng cho một hàm, thông thường kích thước mảng cũng được truyền, vì vậy hàm có thể xử lý số phần tử cụ thể trong mảng. Nếu không, chúng ta sẽ cần xây dựng kiến ​​thức này vào chính hàm được gọi hoặc tệ hơn là đặt kích thước mảng vào một biến toàn cục.
  • C ++ chuyển mảng cho các hàm bằng cách tham chiếu, tức là các hàm được gọi có thể sửa đổi các giá trị phần tử trong mảng ban đầu của người gọi.
  • Giá trị tên của mảng là địa chỉ trong bộ nhớ máy tính của phần tử đầu tiên của mảng. Vì địa chỉ bắt đầu của mảng được truyền, hàm được gọi sẽ biết chính xác vị trí mà mảng được lưu trong bộ nhớ. Do đó, khi hàm được gọi sửa đổi các phần tử mảng trong thân hàm của nó, nó đang sửa đổi các phần tử thực của mảng trong vị trí bộ nhớ ban đầu của chúng.
  • Mặc dù toàn bộ mảng được truyền bằng tham chiếu, nhưng các phần tử mảng riêng lẻ được chuyển theo giá trị chính xác như các biến đơn giản.
  • Để chuyển một phần tử của mảng cho một hàm, hãy sử dụng tên được ký hiệu con của phần tử mảng làm đối số trong lệnh gọi hàm.
  • Đối với một hàm nhận một mảng thông qua một lời gọi hàm, danh sách tham số của hàm phải chỉ định rằng hàm mong đợi nhận một mảng.
  • Ví dụ: tiêu đề hàm cho hàm modArray có thể được viết là:
void modifyArray( int b[], int arraySize )
  • Câu lệnh cho biết rằng modArray mong đợi nhận được địa chỉ của một mảng các số nguyên trong tham số b và số phần tử mảng trong tham số arraySize. Kích thước của mảng không bắt buộc trong dấu ngoặc của mảng. Nếu nó được bao gồm, trình biên dịch sẽ bỏ qua nó; do đó, các mảng có kích thước bất kỳ có thể được chuyển cho hàm.
  • C ++ chuyển mảng cho các hàm bằng cách tham chiếu. Khi hàm được gọi sử dụng tên mảng b, nó tham chiếu đến mảng thực tế trong trình gọi (tức là, arrayhourlyTempe Nhiệt độ được thảo luận ở đầu phần này).

Lưu ý sự xuất hiện kỳ ​​lạ của nguyên mẫu hàm cho modArray.

void modifyArray( int [] , int ) ;

Nguyên mẫu này có thể đã được viết theo cách sau đây cho mục đích tài liệu.

void modifyArray( int anyArrayName[], int anyVariableName ) ;

Tuy nhiên, trình biên dịch C ++ bỏ qua tên biến trong nguyên mẫu. Hãy nhớ rằng, nguyên mẫu cho trình biên dịch biết số lượng đối số và kiểu của mỗi đối số theo thứ tự mà các đối số được mong đợi xuất hiện.

Chương trình trong ví dụ tiếp theo thể hiện sự khác biệt giữa truyền toàn bộ mảng và truyền một phần tử mảng.

Thí dụ

void modifyArray( int [], int ); // appears strange; array and size
void modifyElement( int ); // receive array element value

void setup () {
   Serial.begin (9600);
   const int arraySize = 5; // size of array a
   int a[ arraySize ] = { 0, 1, 2, 3, 4 }; // initialize array a
   Serial.print ( "Effects of passing entire array by reference:" ) ;
   // output original array elements
   for ( int i = 0; i < arraySize ; ++i )
   Serial.print ( a[ i ] ) ;
   Serial.print ("\r" ) ;
   Serial.print ("The values of the modified array are:\n" );
   // output modified array elements
   for ( int j = 0; j < arraySize; ++j )
   Serial.print ( a[j ] ) ;
   Serial.print ("\r" ) ;
   Serial.print ("\r\rEffects of passing array element by value:" );
   Serial.print ( "\ra[3] before modifyElement: " );
   Serial.print ( a[ 3 ] );
   Serial.print ( "\ra[3] after modifyElement: " );
   Serial.print ( a[ 3 ] );
}

void loop () {

}

// in function modifyArray, "b" points to the original array "a" in memory

void modifyArray( int b[], int sizeOfArray ) {
   // multiply each array element by 2
   for ( int k = 0 ; k < sizeOfArray ; ++k )
   b[ k ] *= 2;
} 

// end function modifyArray
// in function modifyElement, "e" is a local copy of
// array element a[ 3 ] passed from main

void modifyElement( int e ) {
   // multiply parameter by 2
   Serial.print ( "Value of element in modifyElement: " );
   Serial.print ( ( e *= 2 ) );
} 

// end function modifyElement

Kết quả

Effects of passing entire array by reference:01234
The values of the modified array are:01234
Effects of passing array element by value:
a[3] before modifyElement: 3
a[3] after modifyElement: 3
$ is not a hexadecimal digit

f is a hexadecimal digit

Arduino – Mảng đa chiều

Mảng có hai thứ nguyên (tức là chỉ số con) thường đại diện cho bảng giá trị bao gồm thông tin được sắp xếp theo hàng và cột.

Sau đây là các tính năng chính của mảng đa chiều:

  • Để xác định một phần tử bảng cụ thể, chúng ta phải chỉ định hai chỉ số con.
  • Theo quy ước, đầu tiên xác định hàng của phần tử và thứ hai xác định cột của phần tử.
  • Mảng yêu cầu hai chỉ số con để xác định một phần tử cụ thể được gọi là mảng hai chiều hoặc mảng 2-D.
  • Mảng có hai hoặc nhiều kích thước được gọi là mảng nhiều chiều và có thể có nhiều hơn hai chiều.

Hình sau minh họa một mảng hai chiều, a . Mảng chứa ba hàng và bốn cột, vì vậy nó là một mảng 3 x 4. Nói chung, một mảng có m hàng và n cột được gọi là mảng m-x-n .

Mọi phần tử trong mảng a được xác định bằng tên phần tử có dạng a [i] [j] . Ở đây, a là tên của mảng và i và j là các chỉ số con xác định duy nhất từng phần tử trong a . Chú ý rằng tên của các phần tử trong hàng 0 đều có chỉ số con đầu tiên là 0; tên của các phần tử trong cột 3 đều có chỉ số con thứ hai là 3.

Một mảng nhiều chiều có thể được khởi tạo trong phần khai báo của nó giống như một mảng một chiều. Ví dụ, một mảng hai chiều b với các giá trị 1 và 2 trong các phần tử 0 ở hàng của nó và các giá trị 3 và 4 trong các phần tử 1 của nó có thể được khai báo và khởi tạo như sau:

int b[ 2 ][ 2 ] = { { 1, 2 }, { 3, 4 } };

Các giá trị được nhóm theo hàng trong dấu ngoặc nhọn. Do đó, 1 và 2 lần lượt khởi tạo b [0] [0] và b [0] [1], và 3 và 4 lần lượt khởi tạo b [1] [0] và b [1] [1]. Nếu không có đủ bộ khởi tạo cho một hàng nhất định, các phần tử còn lại của hàng đó được khởi tạo thành 0. Do đó, khai báo sau khởi tạo b [0] [0] thành 1, b [0] [1] thành 0, b [ 1] [0] thành 3 và b [1] [1] thành 4.

int b[ 2 ][ 2 ] = { { 1 }, { 3, 4 } };

Thí dụ

Đây là một ví dụ minh họa việc khởi tạo mảng hai chiều trong khai báo.

  • Các dòng a – c khai báo ba mảng, mỗi mảng có hai hàng và ba cột.
  • Khai báo array1 (dòng a) cung cấp sáu bộ khởi tạo trong hai danh sách con. Danh sách con đầu tiên khởi tạo hàng 0 của mảng thành các giá trị 1, 2 và 3; danh sách con thứ hai khởi tạo hàng 1 của mảng thành các giá trị 4, 5 và 6.
  • Nếu các dấu ngoặc nhọn xung quanh mỗi danh sách con bị xóa khỏi danh sách bộ khởi tạo array1, trình biên dịch sẽ khởi tạo các phần tử của hàng 0 theo sau là các phần tử của hàng 1, cho ra kết quả tương tự.
  • Khai báo array2 (dòng b ) chỉ cung cấp năm bộ khởi tạo.
  • Các bộ khởi tạo được gán cho hàng 0, sau đó đến hàng 1. Bất kỳ phần tử nào không có bộ khởi tạo rõ ràng đều được khởi tạo bằng 0, do đó, array2 [1] [2] được khởi tạo bằng 0.
  • Khai báo array3 (dòng c ) cung cấp ba bộ khởi tạo trong hai danh sách con.
  • Danh sách con cho hàng 0 khởi tạo rõ ràng hai phần tử đầu tiên của hàng 0 thành 1 và 2; phần tử thứ ba được khởi tạo ngầm định bằng 0.
  • Danh sách phụ cho hàng 1 khởi tạo rõ ràng phần tử đầu tiên thành 4 và mặc nhiên khởi tạo hai phần tử cuối cùng bằng 0.
  • Chương trình gọi hàm printArray để xuất ra từng phần tử của mảng. Chú ý rằng nguyên mẫu hàm (dòng k ) chỉ định tham số const int a [] [cột] .
  • Khi một hàm nhận mảng một chiều làm đối số, thì các dấu ngoặc mảng sẽ trống trong danh sách tham số của hàm.
  • Kích thước của kích thước đầu tiên của mảng hai chiều (tức là số hàng) cũng không bắt buộc, nhưng tất cả các kích thước thứ nguyên tiếp theo là bắt buộc. Trình biên dịch sử dụng các kích thước này để xác định vị trí trong bộ nhớ của các phần tử trong mảng nhiều chiều.

Tất cả các phần tử mảng được lưu trữ liên tiếp trong bộ nhớ, bất kể số thứ nguyên. Trong mảng hai chiều, hàng 0 được lưu trong bộ nhớ, tiếp theo là hàng 1.

Thí dụ

void printArray ( const int [][ 3 ] ); // prototype
const int rows = 2;
const int columns = 3;
int array1[ rows ][ columns ] = { { 1, 2, 3 }, { 4, 5, 6 } };
int array2[ rows ][ columns ] = { 1, 2, 3, 4, 5 };
int array3[ rows ][ columns ] = { { 1, 2 }, { 4 } };

void setup () {

}
void loop () {
   Serial.print ("Values in array1 by row are: ") ;
   Serial.print (“\r” ) ;
   printArray(array1) ;
   Serial.print ("Values in array2 by row are: ") ;
   Serial.print (“\r” ) ;
   printArray(array2) ;
   Serial.print ("Values in array3 by row are: ") ;
   Serial.print (“\r” ) ;
   printArray(array3) ;
}

// output array with two rows and three columns

void printArray( const int a[][ columns ] ) {
   // loop through array's rows
   for ( int i = 0; i < rows; ++i ) {
      // loop through columns of current row
      for ( int j = 0; j < columns; ++j )
      Serial.print (a[ i ][ j ] );
      Serial.print (“\r” ) ; // start new line of output
   } 
// end outer for
} 

// end function printArray

Kết quả

Values in array1 by row are:
1 2 3
4 5 6
Values in array2 by row are:
1 2 3
4 5 0
Values in array3 by row are:
1 2 0
4 0 0

Lưu ý – Mỗi hàng là một mảng một chiều. Để định vị một phần tử trong một hàng cụ thể, hàm phải biết chính xác có bao nhiêu phần tử trong mỗi hàng để nó có thể bỏ qua số lượng vị trí bộ nhớ thích hợp khi truy cập vào mảng. Do đó, khi truy cập vào một [1] [2], hàm biết bỏ qua ba phần tử của hàng 0 trong bộ nhớ để đến hàng 1. Sau đó, hàm truy cập phần tử 2 của hàng đó. Nhiều thao tác mảng phổ biến sử dụng câu lệnh FOR .

Ví dụ, câu lệnh FOR sau đây đặt tất cả các phần tử trong hàng 2 của mảng a .

for ( int column = 0; column < 4; ++column )
   a[ 2 ][ column ] = 0;

Câu lệnh FOR chỉ thay đổi chỉ số con thứ hai (tức là chỉ số phụ cột). Câu lệnh FOR trước tương đương với các câu lệnh gán sau:

a[ 2 ][ 0 ] = 0;
a[ 2 ][ 1 ] = 0;
a[ 2 ][ 2 ] = 0;
a[ 2 ][ 3 ] = 0;

Câu lệnh FOR lồng nhau sau đây xác định tổng tất cả các phần tử trong mảng a –

total = 0;
for ( int row = 0; row < 3; ++row )
for ( int column = 0; column < 4; ++column )
total += a[ row ][ column ];

Câu lệnh FOR tính tổng các phần tử của mảng một hàng tại một thời điểm. Câu lệnh FOR bên ngoài bắt đầu bằng cách đặt hàng (tức là chỉ số con của hàng) thành 0. Do đó, các phần tử của hàng 0 có thể được tính tổng bằng câu lệnh FOR bên trong . Sau đó, câu lệnh FOR bên ngoài tăng hàng lên 1, do đó, các phần tử của hàng 1 có thể được tính tổng. Sau đó, câu lệnh FOR bên ngoài tăng hàng lên 2, do đó, các phần tử của hàng 2 có thể được tính tổng. Khi câu lệnh FOR lồng nhau kết thúc, tổng chứa tổng của tất cả các phần tử mảng.

Arduino – Chức năng I / O

Các chân trên bảng Arduino có thể được cấu hình làm đầu vào hoặc đầu ra. Chúng tôi sẽ giải thích chức năng của các chân trong các chế độ đó. Điều quan trọng cần lưu ý là phần lớn các chân tương tự Arduino, có thể được cấu hình và sử dụng, theo cách giống hệt như các chân kỹ thuật số.

Các ghim được định cấu hình là INPUT

Các chân Arduino theo mặc định được định cấu hình làm đầu vào, vì vậy chúng không cần được khai báo rõ ràng làm đầu vào với pinMode () khi bạn sử dụng chúng làm đầu vào. Các chân được cấu hình theo cách này được cho là ở trạng thái trở kháng cao. Các chân đầu vào tạo ra các yêu cầu cực kỳ nhỏ đối với mạch mà chúng đang lấy mẫu, tương đương với một điện trở nối tiếp 100 megaohm phía trước chân cắm.

Điều này có nghĩa là cần rất ít dòng điện để chuyển chân đầu vào từ trạng thái này sang trạng thái khác. Điều này làm cho các chân trở nên hữu ích cho các tác vụ như triển khai cảm biến cảm ứng điện dung hoặc đọc đèn LED dưới dạng điốt quang.

Các chân được định cấu hình là pinMode (pin, INPUT) mà không có gì được kết nối với chúng hoặc với các dây được kết nối với chúng không được kết nối với các mạch khác, báo cáo các thay đổi dường như ngẫu nhiên trong trạng thái chân, nhận nhiễu điện từ môi trường hoặc trạng thái ghép nối điện dung của một ghim gần đó.

Điện trở kéo lên

Điện trở kéo lên thường hữu ích để điều khiển chân đầu vào đến trạng thái đã biết nếu không có đầu vào. Điều này có thể được thực hiện bằng cách thêm một điện trở kéo lên (đến + 5V) hoặc một điện trở kéo xuống (điện trở nối đất) trên đầu vào. Một điện trở 10K là một giá trị tốt cho một điện trở kéo lên hoặc kéo xuống.

Sử dụng điện trở kéo lên tích hợp với các chân được định cấu hình làm đầu vào

Có 20.000 điện trở kéo lên được tích hợp trong chip Atmega có thể được truy cập từ phần mềm. Các điện trở kéo lên tích hợp này được truy cập bằng cách đặt mã pinMode () là INPUT_PULLUP. Điều này có hiệu quả đảo ngược hoạt động của chế độ INPUT, trong đó CAO nghĩa là cảm biến TẮT và THẤP nghĩa là cảm biến BẬT. Giá trị của phần kéo lên này phụ thuộc vào bộ vi điều khiển được sử dụng. Trên hầu hết các bo mạch dựa trên AVR, giá trị được đảm bảo nằm trong khoảng từ 20kΩ đến 50kΩ. Trên Arduino Due, nó nằm trong khoảng từ 50kΩ đến 150kΩ. Để biết giá trị chính xác, hãy tham khảo biểu dữ liệu của bộ vi điều khiển trên bo mạch của bạn.

Khi kết nối cảm biến với chân được định cấu hình bằng INPUT_PULLUP, đầu kia phải được kết nối với đất. Trong trường hợp một công tắc đơn giản, điều này làm cho chân ghi giá trị CAO khi công tắc mở và THẤP khi công tắc được nhấn. Các điện trở kéo lên cung cấp đủ dòng điện để thắp sáng đèn LED được kết nối mờ với chân được định cấu hình làm đầu vào. Nếu đèn LED trong một dự án dường như đang hoạt động, nhưng rất mờ, đây có thể là điều đang xảy ra.

Các thanh ghi tương tự (vị trí bộ nhớ chip bên trong) kiểm soát việc một chân là CAO hay THẤP kiểm soát các điện trở kéo lên. Do đó, một chân được cấu hình để bật điện trở kéo lên khi chân ở chế độ INPUTmode, sẽ có chân được cấu hình là CAO nếu sau đó chân được chuyển sang chế độ OUTPUT với pinMode (). Điều này cũng hoạt động theo hướng khác và chân đầu ra được để ở trạng thái CAO sẽ có bộ điện trở kéo lên nếu được chuyển sang đầu vào có pinMode ().

Thí dụ

pinMode(3,INPUT) ; // set pin to input without using built in pull up resistor
pinMode(5,INPUT_PULLUP) ; // set pin to input using built in pull up resistor

Các chân được định cấu hình là OUTPUT

Các chân được cấu hình là OUTPUT với pinMode () được cho là ở trạng thái trở kháng thấp. Điều này có nghĩa là chúng có thể cung cấp một lượng dòng điện đáng kể cho các mạch khác. Các chân Atmega có thể cấp nguồn (cung cấp dòng điện dương) hoặc chìm (cung cấp dòng điện âm) lên đến 40 mA (miliampe) dòng điện cho các thiết bị / mạch khác. Đây là dòng điện đủ để làm sáng đèn LED (đừng quên điện trở nối tiếp), hoặc chạy nhiều cảm biến nhưng không đủ dòng điện để chạy các rơ le, solenoid hoặc động cơ.

Cố gắng chạy các thiết bị có dòng điện cao từ các chân đầu ra, có thể làm hỏng hoặc phá hủy các bóng bán dẫn đầu ra trong chân hoặc làm hỏng toàn bộ chip Atmega. Thông thường, điều này dẫn đến một chân “chết” trong bộ vi điều khiển nhưng các chip còn lại vẫn hoạt động đầy đủ. Vì lý do này, bạn nên kết nối các chân OUTPUT với các thiết bị khác thông qua điện trở 470Ω hoặc 1k, trừ khi dòng điện tối đa rút ra từ các chân được yêu cầu cho một ứng dụng cụ thể.

hàm pinMode ()

Hàm pinMode () được sử dụng để định cấu hình một chân cụ thể hoạt động như một đầu vào hoặc đầu ra. Có thể kích hoạt các điện trở kéo lên bên trong với chế độ INPUT_PULLUP. Ngoài ra, chế độ INPUT vô hiệu hóa rõ ràng các pull-up bên trong.

Cú pháp hàm pinMode ()

Void setup () {
   pinMode (pin , mode);
}
  • pin – số pin có chế độ bạn muốn đặt

chế độ – INPUT, OUTPUT hoặc INPUT_PULLUP.

Thí dụ

int button = 5 ; // button connected to pin 5
int LED = 6; // LED connected to pin 6

void setup () {
   pinMode(button , INPUT_PULLUP); 
   // set the digital pin as input with pull-up resistor
   pinMode(button , OUTPUT); // set the digital pin as output
}

void setup () {
   If (digitalRead(button ) == LOW) // if button pressed {
      digitalWrite(LED,HIGH); // turn on led
      delay(500); // delay for 500 ms
      digitalWrite(LED,LOW); // turn off led
      delay(500); // delay for 500 ms
   }
}

Hàm digitalWrite ()

Hàm digitalWrite () được sử dụng để ghi giá trị CAO hoặc THẤP vào chân số. Nếu chân đã được cấu hình như một OUTPUT với pinMode () , điện áp của nó sẽ được đặt thành giá trị tương ứng: 5V (hoặc 3.3V trên bảng 3.3V) đối với CAO, 0V (đất) đối với THẤP. Nếu chân được định cấu hình là ĐẦU VÀO, digitalWrite () sẽ bật (CAO) hoặc tắt (THẤP) kéo lên bên trong trên chân đầu vào. Bạn nên đặt pinMode () thành INPUT_PULLUP để kích hoạt điện trở kéo lên bên trong.

Nếu bạn không đặt pinMode () thành OUTPUT và kết nối đèn LED với chân cắm, khi gọi digitalWrite (HIGH), đèn LED có thể bị mờ. Nếu không thiết lập rõ ràng pinMode (), digitalWrite () sẽ kích hoạt điện trở kéo lên bên trong, hoạt động giống như một điện trở hạn chế dòng điện lớn.

Cú pháp hàm digitalWrite ()

Void loop() {
   digitalWrite (pin ,value);
}
  • pin – số pin có chế độ bạn muốn đặt
  • giá trị – CAO hoặc THẤP.

Thí dụ

int LED = 6; // LED connected to pin 6

void setup () {
   pinMode(LED, OUTPUT); // set the digital pin as output
}

void setup () { 
   digitalWrite(LED,HIGH); // turn on led
   delay(500); // delay for 500 ms
   digitalWrite(LED,LOW); // turn off led
   delay(500); // delay for 500 ms
}

hàm analogRead ()

Arduino có thể phát hiện xem có điện áp đặt vào một trong các chân của nó hay không và báo cáo nó thông qua hàm digitalRead (). Có sự khác biệt giữa cảm biến bật / tắt (phát hiện sự hiện diện của vật thể) và cảm biến tương tự, có giá trị liên tục thay đổi. Để đọc loại cảm biến này, chúng ta cần một loại chân cắm khác.

Ở phần dưới bên phải của bảng Arduino, bạn sẽ thấy sáu chân được đánh dấu “Analog In”. Các chân đặc biệt này không chỉ cho biết có điện áp đặt vào chúng hay không mà còn cho biết giá trị của nó. Bằng cách sử dụng hàm analogRead () , chúng ta có thể đọc điện áp đặt vào một trong các chân.

Hàm này trả về một số từ 0 đến 1023, đại diện cho điện áp từ 0 đến 5 vôn. Ví dụ: nếu có một điện áp 2,5 V được áp dụng cho chân số 0, analogRead (0) trả về 512.

Cú pháp hàm analogRead ()

analogRead(pin);
  • pin – số lượng chân đầu vào tương tự để đọc (0 đến 5 trên hầu hết các bo mạch, 0 đến 7 trên Mini và Nano, 0 đến 15 trên Mega)

Thí dụ

int analogPin = 3;//potentiometer wiper (middle terminal) 
   // connected to analog pin 3 
int val = 0; // variable to store the value read

void setup() {
   Serial.begin(9600); // setup serial
} 

void loop() {
   val = analogRead(analogPin); // read the input pin
   Serial.println(val); // debug value
}

Arduino – Chức năng I / O nâng cao xem thêm

Trả lời