Mắt người không phản ứng tuyến tính với cường độ ánh sáng (phi tuyến tính), bạn xuất 1 PWM có giá trị gấp đôi, điện áp trung bình trên led gấp đôi, led sáng cường độ gấp đôi, nhưng chưa chắc mắt bạn đã cảm nhận được độ sáng gấp đôi. Bạn điều khiển 1 bóng led với PWM từ 0 đến 255 thì hầu như từ giá trị thứ 200 trở lên gần như chả có tí khác biệt gì về độ sáng cả T.T
Hiệu chỉnh Gamma là xắp xếp lại các giá trị sáng theo 1 tỉ lệ logarit (hoặc hàm nào đó) ánh sáng phát ra được đẹp nhất
Nếu mục tiêu của bạn là điều khiển LED với 8bit POWM. Bạn có thể tăng số bit PWM lên 9bit 10bit … rồi hiệu chỉnh. Đây là cách rất hay và hiệu quả nhưng đổi lại sẽ hao tốn tài nguyên vi điều khiển hơn do phải xuất pwm độ phân giải cao hơn
1 công thức biến đổi PWM cơ bản có thể như sau:
o = (int)(pow((float)i / (float)max_in, gamma) * max_out
Với:
o là giá trị pwm output
i là giá trị PWM input
max_in là giá trị PWM đầu vào tối đa cho phép
max_out là giá trị PWM đầu ra tối đa cho phép
gamma là hệ số chuyển đổi
Các phép tính toán gamma làm việc với dấu chậm động và các hàm toán học nên sẽ không hiệu quả chút nào nếu cố đưa nó vào code của vi điều khiển, do đó chúng ta sẽ tính sẵn và đưa nó vào bảng tra cho tiện lợi, các bạn có thể dụng đoạn code C sau để xuất ra bảng tra PWM ( chạy trên DEV-C++ hay Code block hoặc 1 ide C,C++ bất kì nhé)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#include <iostream> #include <math.h> #include <stdio.h> float gamma = 2.3; // Correction factor int max_in = 127, // Top end of INPUT range max_out = 255; // Top end of OUTPUT range int main(int argc, char** argv) { printf("//Bang tra cuu gamma %.1f %i -> %i\n",gamma,max_in,max_out); if(max_out<=255) printf("const unsigned char gamma[]={\r\n"); else printf("const uint8_t gamma[]={\r\n"); for(int i=0;i<max_in+1;i++) { if(i > 0) printf(","); if((i & 15) == 0) printf("\n "); printf("%3d",(int)(pow((float)i / (float)max_in, gamma) * max_out + 0.5)); } printf(" };"); return 0; } |
Ví dụ mình cần 1 bảng tra với hệ số gamma là 2.3, đầu vào 7bit(max là 2mũ7 – 1 = 127 và xuất ra 8bit(max là 2 mũ 8 – 1 = 255), chỉnh sửa các giá trị mong muốn và run code sẽ được bảng tra:
1 số tài liệu tham khảo:
- https://hoc3dmax.com/vray/gamma-la-gi-tai-sao-ton-tai-va-cach-kiem-soat-phan-2.html
- https://en.wikipedia.org/wiki/Gamma_correction
- https://vi.wikipedia.org/wiki/M%C3%B4_h%C3%ACnh_m%C3%A0u_RGB#Phi_tuy%E1%BA%BFn_t%C3%ADnh
- https://hackaday.com/2016/08/23/rgb-leds-how-to-master-gamma-and-hue-for-perfect-brightness/
- https://learn.adafruit.com/led-tricks-gamma-correction/the-issue