I'm using an Arduino Mega to run three TSL1401R-LF Linear Scan Cameras in parallel. I got everything working and the camera were giving me different results based on how much light was hitting them (i.e. lots of light gave me a high number and little light gave me a smaller number).
However when I attempted to increase the FPS of the cameras by reducing the delays using no-ops the accuracy fell dramatically and I have no idea why. According to the datasheet the minimum delays for the CLK impulse is 50 ns and a no-op causes a delay of 62.5 ns so there should't be a problem. Anyone on here have and idea as to why this could be happening?
Here is my code before the no-ops:
void readPixels()
{
digitalWrite(SI, HIGH);
delayMicroseconds(delayTime/2);
digitalWrite(CLK, HIGH);
delayMicroseconds(delayTime/2);
digitalWrite(SI, LOW);
delayMicroseconds(delayTime/2);
digitalWrite(CLK, LOW);
delayMicroseconds(delayTime);
for(int i = 0; i < 128; i++)
{
digitalWrite(CLK, HIGH);
pixelsArray1[i]=analogRead(Cam1Aout);
pixelsArray2[i]=analogRead(Cam2Aout);
pixelsArray3[i]=analogRead(Cam3Aout);
delayMicroseconds(delayTime);
digitalWrite(CLK, LOW);
delayMicroseconds(delayTime);
}
delayMicroseconds(20);
}
OUTPUT:
Camera 1: 295, 319, 353, 387, 422, 458, 483, 499, 515, 527, 540, 545, 556, 562, 572, 575, 585, 590, 596, 598, 606, 603, 591, 589, 608, 621, 635, 636, 646, 652, 664, 670, 681, 689, 699, 705, 715, 726, 730, 734, 742, 745, 750, 752, 760, 764, 769, 766, 768, 770, 775, 777, 792, 806, 828, 852, 880, 907, 931, 956, 989, 1016, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 980, 986, 935, 935, 893, 892, 856, 847, 812, 801, 774, 760, 731, 713, 683, 647, 605, 564, 513, 470, 410, 369, 323, 289, 347, 376,
Camera 2: 346, 368, 396, 419, 446, 462, 480, 496, 516, 531, 549, 559, 571, 579, 593, 600, 611, 619, 628, 636, 647, 651, 660, 667, 676, 679, 687, 696, 704, 710, 719, 725, 732, 735, 743, 743, 752, 758, 764, 768, 775, 777, 783, 788, 793, 798, 803, 806, 809, 814, 818, 822, 827, 831, 831, 833, 836, 839, 841, 839, 843, 843, 844, 839, 841, 836, 831, 830, 831, 830, 831, 834, 841, 847, 861, 867, 880, 894, 902, 911, 918, 935, 940, 956, 960, 976, 973, 991, 984, 1007, 998, 1020, 998, 1019, 992, 1014, 986, 997, 964, 969, 937, 937, 908, 910, 878, 875, 843, 838, 808, 797, 768, 750, 720, 696, 667, 639, 611, 582, 556, 524, 499, 471, 449, 423, 399, 371, 396, 399,
Camera 3: 472, 491, 507, 512, 526, 551, 564, 572, 583, 588, 583, 586, 587, 593, 603, 604, 604, 608, 611, 617, 617, 621, 625, 629, 635, 641, 635, 645, 661, 668, 671, 675, 678, 680, 685, 688, 688, 690, 691, 694, 696, 701, 701, 704, 699, 706, 705, 706, 713, 715, 718, 719, 719, 719, 720, 721, 723, 731, 737, 736, 739, 743, 748, 751, 755, 758, 760, 763, 766, 768, 769, 773, 775, 777, 777, 780, 787, 791, 790, 787, 781, 779, 769, 763, 760, 758, 755, 750, 743, 741, 744, 748, 743, 740, 750, 755, 774, 783, 790, 797, 802, 810, 807, 818, 806, 807, 796, 796, 785, 777, 759, 748, 728, 715, 696, 681, 664, 647, 625, 606, 579, 558, 536, 508, 484, 467, 432, 427,
Runetime: 2121
Here it is after the no-ops are added:
void readPixels()
{
digitalWrite(SI, HIGH);
delayMicroseconds(delayTime/2);
digitalWrite(CLK, HIGH);
delayMicroseconds(delayTime/2);
digitalWrite(SI, LOW);
delayMicroseconds(delayTime/2);
digitalWrite(CLK, LOW);
delayMicroseconds(delayTime);
for(int i = 0; i < 128; i++)
{
digitalWrite(CLK, HIGH);
pixelsArray1[i]=analogRead(Cam1Aout);
pixelsArray2[i]=analogRead(Cam2Aout);
pixelsArray3[i]=analogRead(Cam3Aout);
__asm__("nop\n\t");
digitalWrite(CLK, LOW);
__asm__("nop\n\t");
}
delayMicroseconds(20);
}
OUTPUT:
Camera 1: 147, 141, 142, 143, 145, 145, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 146, 145, 145, 143, 145, 143, 146, 146, 145, 145, 144, 147, 147, 147, 147, 148, 147, 147, 147, 147, 147, 147, 147, 147, 147, 148, 147, 147, 147, 148, 147, 147, 148, 147, 151, 152, 153, 154, 156, 156, 158, 158, 159, 161, 162, 163, 165, 166, 167, 167, 168, 169, 167, 172, 174, 174, 174, 174, 175, 176, 176, 177, 177, 179, 179, 179, 179, 179, 178, 178, 176, 175, 174, 172, 172, 170, 168, 167, 165, 163, 162, 161, 159, 158, 156, 154, 155, 152, 151, 150, 148, 146, 146, 143, 143, 141, 139, 137, 135, 131, 129, 127, 125, 122, 120, 140, 172,
Camera 2: 162, 161, 164, 164, 167, 166, 165, 167, 169, 167, 170, 171, 171, 169, 172, 171, 172, 171, 172, 172, 172, 172, 173, 172, 173, 172, 174, 173, 174, 173, 174, 174, 176, 174, 175, 170, 175, 174, 176, 175, 185, 175, 176, 175, 176, 175, 176, 176, 176, 176, 176, 176, 177, 176, 177, 176, 176, 176, 177, 176, 177, 176, 177, 176, 176, 176, 176, 176, 176, 175, 176, 175, 176, 176, 177, 177, 179, 177, 179, 179, 179, 179, 181, 181, 183, 183, 184, 184, 185, 185, 186, 185, 187, 186, 187, 187, 188, 185, 186, 184, 185, 183, 183, 181, 181, 179, 179, 176, 176, 174, 174, 172, 171, 170, 167, 164, 164, 162, 161, 159, 159, 156, 157, 154, 153, 152, 169, 198,
Camera 3: 185, 187, 188, 191, 189, 190, 192, 192, 193, 193, 192, 194, 194, 194, 195, 199, 196, 196, 196, 197, 199, 198, 198, 198, 199, 199, 199, 199, 196, 201, 201, 201, 201, 201, 202, 203, 202, 202, 203, 203, 204, 204, 204, 203, 204, 204, 204, 204, 204, 204, 205, 205, 205, 206, 206, 206, 205, 206, 206, 206, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 208, 207, 209, 209, 208, 208, 209, 209, 207, 208, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 208, 209, 209, 209, 211, 211, 211, 211, 211, 211, 211, 210, 210, 209, 209, 207, 207, 206, 206, 204, 203, 203, 201, 199, 200, 198, 195, 195, 195, 193, 167, 179,
Runetime: 1987
Here it is with me using While Loops:
void readPixels()
{
digitalWrite(SI, HIGH);
delayMicroseconds(delayTime/2);
digitalWrite(CLK, HIGH);
delayMicroseconds(delayTime/2);
digitalWrite(SI, LOW);
delayMicroseconds(delayTime/2);
digitalWrite(CLK, LOW);
delayMicroseconds(delayTime);
int i = 0;
while(i < 128)
{
i++;
digitalWrite(CLK, HIGH);
pixelsArray1[i]=analogRead(Cam1Aout);
pixelsArray2[i]=analogRead(Cam2Aout);
pixelsArray3[i]=analogRead(Cam3Aout);
digitalWrite(CLK, LOW);
}
delayMicroseconds(20);
}
OUTPUT:
Camera 1: 224, 161, 172, 179, 185, 198, 199, 203, 206, 208, 208, 211, 212, 213, 214, 216, 216, 217, 217, 218, 217, 219, 219, 216, 215, 217, 220, 222, 223, 223, 224, 226, 225, 229, 231, 231, 232, 235, 235, 236, 237, 238, 240, 240, 240, 240, 241, 242, 242, 242, 242, 243, 243, 246, 248, 252, 255, 262, 266, 271, 276, 281, 287, 291, 296, 304, 307, 314, 319, 326, 332, 331, 337, 337, 335, 352, 359, 359, 359, 361, 366, 371, 371, 372, 376, 382, 384, 384, 382, 380, 380, 377, 372, 366, 361, 355, 351, 344, 339, 331, 323, 318, 312, 307, 301, 294, 290, 284, 280, 273, 268, 263, 257, 252, 248, 241, 231, 227, 219, 209, 199, 191, 182, 172, 163, 155, 147, 176,
Camera 2: 216, 193, 196, 203, 207, 212, 216, 219, 222, 223, 227, 231, 231, 234, 236, 238, 239, 241, 242, 242, 244, 247, 247, 248, 249, 252, 252, 252, 254, 255, 258, 259, 259, 259, 260, 262, 262, 263, 263, 265, 272, 268, 267, 268, 268, 270, 270, 271, 271, 272, 273, 274, 275, 275, 275, 276, 276, 277, 277, 278, 277, 280, 278, 278, 277, 278, 276, 276, 275, 275, 275, 275, 276, 277, 278, 280, 282, 285, 287, 289, 291, 294, 295, 299, 301, 304, 306, 310, 312, 313, 316, 319, 319, 321, 322, 323, 323, 322, 319, 318, 315, 312, 308, 305, 302, 298, 294, 289, 284, 280, 275, 270, 263, 257, 251, 244, 238, 232, 227, 223, 216, 211, 206, 202, 197, 193, 188, 207,
Camera 3: 0, 231, 235, 238, 240, 243, 247, 250, 252, 254, 255, 255, 255, 255, 257, 259, 260, 260, 260, 262, 260, 263, 264, 265, 266, 267, 268, 268, 269, 273, 274, 276, 275, 276, 277, 278, 278, 279, 279, 280, 280, 280, 281, 281, 281, 281, 283, 283, 283, 284, 284, 285, 285, 285, 286, 286, 286, 286, 287, 289, 289, 289, 290, 291, 291, 292, 293, 293, 294, 294, 295, 295, 295, 295, 295, 296, 297, 298, 299, 299, 298, 297, 296, 295, 294, 294, 292, 292, 291, 290, 289, 291, 291, 290, 289, 291, 292, 295, 298, 300, 302, 304, 304, 307, 307, 307, 305, 304, 304, 303, 300, 297, 294, 289, 287, 283, 280, 275, 272, 269, 263, 259, 255, 252, 246, 241, 237, 212,
Runetime: 1991
Some notes:
-
I've optimized the
analogRead();
method with prescalers so they are faster than usual. -
While the output of the second code does show some difference when I hold an object in the line of site of the cameras it is a much smaller difference and only works when I'm holding it directly in front of the cameras.
Best Answer
What most probably happened is the compiler decided to optimize your code and threw those
nop
's away. You should force the compiler to keep your assembly intact by defining itvolatile
:Alternatively, you could make a delay by doing something useful, for example:
PS. The drop in sensitivity you are seeing may well be normal. Your datasheet says:
Since your optimized code runs faster, there is less time left for integration, which reduces the output value.
Also, try adding a delay after
digitalWrite(CLK, HIGH);
to respect thets
time mentioned in the waveform on page 5.