i want to run my 3 axes gantry(stm32) in sequence similar to the sequence of serial data sent from the pc but this is not happening. no data is lost as all the axes perform their task but in wrong sequence.
this is the recieve complete callback loop
`void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(r != ',')
{
Rx[i++] = r;
}
else
{
strncpy(s1,Rx,i);
Home = strrchr(s1, 'H');
StringX = strrchr(s1, 'X');
StringY = strrchr(s1, 'Y');
StringZ = strrchr(s1, 'Z');
StringW = strrchr(s1, 'W');
if(Home[0] == 'H' && Home[1] == 'O' && Home[2] == 'M' && Home[3] == 'E')
{
homeValue = 1;
}
if(StringX[0] == 'X')
{
MoveX= substr(StringX,1,8);
MoveXvalue = (atol(MoveX))/100;
SpeedX = substr(StringX,8,12);
SpeedXvalue = atol(SpeedX);
insertintoQueue_X(MoveXvalue, SpeedXvalue);
insertintoSequenceQueue (1);
}
if(StringY[0] == 'Y')
{
MoveY= substr(StringY,1,8);
MoveYvalue = (atol(MoveY))/100;
SpeedY = substr(StringY,8,12);
SpeedYvalue = atol(SpeedY);
insertintoQueue_Y(MoveYvalue, SpeedYvalue);
insertintoSequenceQueue (2);
///goes on for other axes
/
i = 0;
}
}`
i tried sequencing these received cmds with below loop(posting only for one axis)
`void insertintoQueue_X (int j, int l)
{
uint8_t queuefull[] = "XFULL";
if(countXmove == 256 || countXspeed == 256 )
{
HAL_UART_Transmit_IT (&huart1, queuefull, sizeof (queuefull));
}
Xmovequeue[countXmove] = j ;
countXmove++;
Xspeedqueue[countXspeed] = l;
countXspeed++;
}
void removefromQueue_X()
{
//uint8_t queueEmpty[] = "XEMPTY";
/*if(countXmove == 0 || countXspeed == 0)
{
HAL_UART_Transmit_IT (&huart2, queueEmpty, sizeof (queueEmpty));
}*/
currentXmoveelement = Xmovequeue[0];
currentXspeedelement = Xspeedqueue[0];
for(int i = 0; i < countXmove - 1; i++)
{
Xmovequeue[i] = Xmovequeue[i+1];
Xspeedqueue[i] = Xspeedqueue[i+1];
}
}`
while loop is as below
` removefromSequenceQueue();//only called once in while loop
for(int p = 0; p < countXmove ; p++)
{
if(currentSequence == 1)
{
removefromQueue_X();
if(currentXmoveelement >0)
{
//uint8_t Xmovvestatus[] = "XMMM";
if(CurrentXposition != currentXmoveelement)
{
if(CurrentXposition > currentXmoveelement )
{
currentmoveX = CurrentXposition - currentXmoveelement;
motorMoveTo(currentmoveX,0,currentXspeedelement,20,SMSPR_X,SMS_X,SMDPR_X,SMD_X);
}
else if(CurrentXposition < currentXmoveelement )
{
// HAL_UART_Transmit_IT (&huart1, Xmovvestatus, sizeof (Xmovvestatus));
currentmoveX = currentXmoveelement - CurrentXposition ;
motorMoveTo(currentmoveX,1,currentXspeedelement,20,SMSPR_X,SMS_X,SMDPR_X,SMD_X);
}
CurrentXposition = currentXmoveelement;
currentXmoveelement = 0;
currentmoveX = 0;
MoveXvalue=0;
}
}
}
}
I have data from a camera in mono 8bit.
This is converted into an int vector using
std::vector<int> grayVector(size);
// convert / copy pointer data into vector: 8 bit
if (static_cast<XI_IMG_FORMAT>(format) == XI_MONO8)
{
quint8* imageIterator = reinterpret_cast<quint8*> (pMemVoid);
for (size_t count = 0; count < size; ++count)
{
grayVector[count] = static_cast<int>(*imageIterator);
imageIterator++;
}
}
Next, I need to convert this into a QImage. If I set the image format to QImage::Format_Mono the app crashes. With QImage::Format_RGB16 I get strippes, and with QImage::Format_RGB32 everything is black.
I would like to know how to do this the best, efficient and correct way?
// convert gray values into QImage data
QImage image = QImage(static_cast<int>(sizeX), static_cat<int>(sizeY), QImage::Format_RGB16);
for ( int y = 0; y < sizeY; ++y )
{
int yoffset = sizeY*y;
QRgb *line = reinterpret_cast<QRgb *>(image.scanLine(y)) ;
for ( int x = 0; x < sizeX ; ++x )
{
int pos = x + yoffset;
int color = grayVector[static_cast<size_t>(pos)];
*line++ = qRgb(color, color, color);
}
}
The conversion to int is unnecessary and you do it in a very inefficient way; all you need is to use the QImage::Format_Grayscale8 available since Qt 5.5 (mid-2015).
Anyway, what you really want is a way to go from XI_IMG to QImage. The default BP_UNSAFE buffering policy should be adequate - the QImage will do a format conversion, so taking the data from XiApi's internal buffer is OK. Thus the following - all of the conversions are implemented in Qt and are quite efficient - much better than most any naive code.
I didn't check whether some Xi formats may need a BGR swap. If so, then the swap can be set to true in the format selection code and the rest will happen automatically.
See also: xiAPI manual.
static QVector<QRgb> grayScaleColorTable() {
static QVector<QRgb> table;
if (table.isEmpty()) {
table.resize(256);
auto *data = table.data();
for (int i = 0; i < table.size(); ++i)
data[i] = qRgb(i, i, i);
}
return table;
}
constexpr QImage::Format grayScaleFormat() {
return (QT_VERSION >= QT_VERSION_CHECK(5,5,0))
? QImage::Format_Grayscale8
: QImage::Format_Indexed8;
}
QImage convertToImage(const XI_IMG *src, QImage::Format f) {
Q_ASSERT(src->fmt == XI_MONO16);
Q_ASSERT((src->padding_x % 2) == 0);
if (src->fmt != XI_MONO16) return {};
const quint16 *s = static_cast<const quint16*>(src->bp);
const int s_pad = src->padding_x/2;
if (f == QImage::Format_BGR30 ||
f == QImage::Format_A2BGR30_Premultiplied ||
f == QImage::Format_RGB30 ||
f == QImage::Format_A2RGB30_Premultiplied)
{
QImage ret{src->width, src->height, f};
Q_ASSERT((ret->bytesPerLine() % 4) == 0);
const int d_pad = ret->bytesPerLine()/4 - ret->width();
quint32 *d = (quint32*)ret.bits();
if (s_pad == d_pad) {
const int N = (src->width + s_pad) * src->height - s_pad;
for (int i = 0; i < N; ++i) {
quint32 const v = (*s++) >> (16-10);
*d++ = 0xC0000000 | v << 20 | v << 10 | v;
}
} else {
for (int j = 0; j < src->height; ++j) {
for (int i = 0; i < src->width; ++i) {
quint32 const v = (*s++) >> (16-10);
*d++ = 0xC0000000u | v << 20 | v << 10 | v;
}
s += s_pad;
d += d_pad;
}
}
return ret;
}
QImage ret{src->width, src->height, grayScaleFormat()};
const int d_pad = ret->bytesPerLine() - ret->width();
auto *d = ret.bits();
if (s_pad == d_pad) {
const int N = (src->width + s_pad) * src->height - s_pad;
for (int i = 0; i < N; ++i) {
*d++ = (*s++) >> 8;
} else {
for (int j = 0; j < src->height; ++j) {
for (int i = 0; i < src->width; ++i)
*d++ = (*s++) >> 8;
s += s_pad;
d += d_pad;
}
}
return ret;
}
QImage fromXiImg(const XI_IMG *src, QImage::Format dstFormat = QImage::Format_ARGB32Premultiplied) {
Q_ASSERT(src->width > 0 && src->height > 0 && src->padding_x >= 0 && src->bp_size > 0);
Q_ASSERT(dstFormat != QImage::Format_Invalid);
bool swap = false;
int srcPixelBytes = 0;
bool externalConvert = false;
QImage::Format srcFormat = QImage::Format_Invalid;
switch (src->fmt) {
case XI_MONO8:
srcPixelBytes = 1;
srcFormat = grayScaleFormat();
break;
case XI_MONO16:
srcPixelBytes = 2;
externalConvert = true;
break;
case XI_RGB24:
srcPixelBytes = 3;
srcFormat = QImage::Format_RGB888;
break;
case XI_RGB32:
srcPixelBytes = 4;
srcFormat = QImage::Format_RGB32;
break;
};
if (srcFormat == QImage::Format_Invalid && !externalConvert) {
qWarning("Unhandled XI_IMG image format");
return {};
}
Q_ASSERT(srcPixelBytes > 0 && srcPixelBytes <= 4);
int bytesPerLine = src->width * srcPixelBytes + src->padding_x;
if ((bytesPerLine * src->height - src->padding_x) > src->bp_size) {
qWarning("Inconsistent XI_IMG data");
return {};
}
QImage ret;
if (!externalConvert)
ret = QImage{static_cast<const uchar*>(src->bp), src->width, src->height,
bytesPerLine, srcFormat};
else
ret = convertToImage(src, dstFormat);
if (ret.format() == QImage::Format_Indexed8)
ret.setColorTable(grayScaleColorTable());
if (ret.format() != dstFormat)
ret = std::move(ret).convertToFormat(dstFormat);
if (swap)
ret = std::move(ret).rgbSwapped();
if (!ret.isDetached()) // ensure that we don't share XI_IMG's data buffer
ret.detach();
return ret;
}
I've been tasked to find the probability of getting a prime number in a Pythagorean triple for a school project, so I tried to code it, but I didn't consider multiples of Pythagorean Triples using Euclid's formula:
(a = m^2 -n^2, b = 2mn, c = m^2 + n^2.).
Ex. 3-4-5 -> 6-8-10.
var primitiveCount = 0;
var m = floor(2), n = floor(1);
var a, b, c;
var ans1, ans2, ans3;
var isPrime = function(value) {
for(var i = 2; i < value; i++) {
if(value % i === 0) {
return false;
}
}
return value > 1;
};
var j=10;
for(var j = 1; j <= 150; j++){
primitiveCount = 0;
m=2;
n=1;
for(var i=0; i < j; i++) {
a = ((Math.pow(m,2))-(Math.pow(n,2)));
b = 2 * n * m;
c = ((Math.pow(m,2))+(Math.pow(n,2)));
if(a<b<c) {
if(Math.pow(a,2) + Math.pow(b,2) === Math.pow(c,2)) {
ans1 = a;
ans2 = b;
ans3 = c;
}
if(isPrime(ans1) || isPrime(ans2) || isPrime(ans3)){
println(ans1 + " " + ans2 + " " + ans3 + " ~");
primitiveCount++;
}else{
println(ans1 + " " + ans2 + " " + ans3);
}
m++;
n++;
}
}
println(primitiveCount + "/" + j);
}
My code creates unique ones, but does not give me the multiples
It is enough to use natural coefficient p
a = p * (m^2 -n^2)
b = p * 2mn
c = p * (m^2 + n^2)
With m>n, m and n coprime and with different parity this method gives all unique triplets.
Conditions together:
p = 1,2,3...
n = 1,2,3...
m = n + 1 + 2 * i, and GCD(m, n) = 1
Seems that your code does not use all values for m, so omits many triplets.
Also use m*m instead of slow pow. Also you don't need to check a^2+b^2=c^2
Currently I'm trying to replicate this wonderful project https://www.youtube.com/watch?v=u8pwmzUVx48, though with more minimum hardware, in which for the classification i'm using a neural network embbeded inside the arduino uno which had been trained offline in more stronger PC. The code of the classifier is here
#include <math.h>
#include <Wire.h>
double dataMagnitude[100];
double feature[7];
double feat_hid[10];
double output[4];
int classi;
const double w_hid[8][10] =
{
{18.9336670380822,11.9186055569093,-5.40114594311576,-21.1410711100689,-49.7798510124792,-14.8215222433047,-34.7308138535581,118.348601654702,-13.6275407707706,-11.6090487951753},
{-21.4994463865001,72.0672467700052,4.05328299052883,21.4875491464005,51.1604296852446,-15.8459578543758,6.30350750703905,-152.565733734759,12.8648040583067,13.8199895673734},
{8.66214515599865,-200.488705071393,-5.86973559011113,-23.4805286444925,-1.11016147795671,-3.04686605995311,-93.4143749063794,-73.8925691072615,-6.18427236042285,-10.9872535411407},
{-12.317892447947,-37.2154526807162,3.83978412266769,2.12866508710205,-11.9740446238331,10.2198116665101,41.9369083083022,63.2036147993661,1.40768362243561,15.4978881385563},
{7.58319670243546,161.895072542918,-2.3654701067923,1.91708846557259,-2.87224127392426,-16.5850302581614,45.2372430254377,34.255971511768,-2.30234070310014,-7.8952356779332},
{0.603971580989218,128.0244079393,0.628535912033608,-1.25788426737745,-0.204480047424961,-41.3372322514891,3.26860448943873,4.163893213914,0.443532051478394,-0.276136697942473},
{-3.63944154925129,18.3802540188974,0.975095285922393,-0.326187652485656,1.25521855841132,39.4877166809573,-15.3542772116519,-14.9546824078715,0.965532742621277,3.72386985716534},
{5.93321854314305,12.673690719929,-3.36580252980446,-21.2089241183081,-10.8980644878121,-7.29095431091201,-30.2240843969778,-2.48980394834853,-5.4167647620581,-5.68671825319015}
}, w_out[11][4] =
{
{1.07887052819228,-21.9615926704441,105.450147012522,-84.5674248703326},
{0.0344508533215184,0.551350792323934,-0.96380329372866,0.37800164808339},
{-99.251397621058,23.1671754381478,7.53147169676884,68.5527504861813},
{-5.0354869957171,4.36918523413481,0.408725687040089,0.257576074543764},
{-27.4478368365984,7.00659524306471,1.74370945871769,18.6975321348269},
{-0.213736004615516,-0.784795805217531,0.0732416484342244,0.925290161399087},
{8.62052547929066,-45.9408034639393,116.959261953552,-79.6389839689755},
{-8.5317661802465,45.4251911929737,-117.146523754862,80.2530987422069},
{127.053878005091,-29.4397580015468,-9.33919798608733,-88.2749220175082},
{1.11869995358251,-21.5111648695486,105.002356379838,-84.6098914639344},
{-5.81786935588552,3.78305066207264,0.11556429335063,-0.0807455995360207}
};
double S, Sig, Sigma, Sigma1, Sigma2, MAV, RMS, VAR, SDT, WL, ZC, SSC, Xn, accum, accumi;
char analogpin = 0, N=100;
void setup()
{
/* add setup code here */
Serial.begin(9600);
Wire.begin();
}
void loop()
{
do{
//data acqusition
for( int i = 0; i<100;i++)
{
Xn = (analogRead(analogpin))-510;
dataMagnitude[i]=Xn;
delayMicroseconds(830);
// Serial.println(dataMagnitude[i]);
}
S = 0;
for (size_t i = 0; i < N; i++)
{
S = S + dataMagnitude[i];
}
Sig = 0;
Sigma = 0;
Sigma1 = 0;
Sigma2 = 0;
for (size_t i = 0; i < N; i++)
{
Sig = Sig + abs(dataMagnitude[i]);
Sigma = Sigma + pow(dataMagnitude[i], 2);
Sigma1 = Sigma1 + pow((dataMagnitude[i] - S / N), 2);
}
for (size_t i = 0; i < N - 1; i++)
{
Sigma2 = Sigma2 + abs(dataMagnitude[i + 1] - dataMagnitude[i]);
}
//featureextract
MAV = (((1 / (double)N)*Sig-27.67)*2/(272.02-27.67))-1;
RMS = (sqrt((1 / (double)N)*Sigma)-34.91002721)*2/(284.1419012-34.91002721)-1;
VAR = (((1 / (double)(N))*Sigma1)-698.4139)*2/(52178.5691-698.4139)-1;
SDT = (sqrt((1 / (double)(N)) * Sigma1)-26.42752164)*2/(228.4262881-26.42752164)-1;
WL = (Sigma2-1621)*2/(11273-1621)-1;
//ZC = 0;
for (size_t i = 0; i < N - 1; i++)
{
if (dataMagnitude[i] == 0 && dataMagnitude[i] != dataMagnitude[i + 1])
{
ZC++;
}
}
ZC = (ZC-0)*2/(39-0)-1;
//SSC = 0;
for (size_t i = 0; i < N - 2; i++)
{
if (dataMagnitude[i]>dataMagnitude[i + 1] && dataMagnitude[i + 1]<dataMagnitude[i + 2])
{
SSC++;
}
else if (dataMagnitude[i]<dataMagnitude[i + 1] && dataMagnitude[i + 1]>dataMagnitude[i + 2])
{
SSC++;
}
}
SSC = (SSC-48)*2/(78-48)-1;
double feature[] = { MAV, RMS, VAR, SDT, WL, ZC, SSC };
//neural network construction
//first-hidden layer
for (int i = 0; i < 10; i++)
{
accum = w_hid[7][i];
for (int j = 0; j < 7; j++)
{
accum += (feature[j] * w_hid[j][i]);
}
feat_hid[i] = tanh(accum);
}
for (int i = 0; i < 4; i++)
{
accumi = w_out[10][i];
for (int j = 0; j < 10; j++)
{
accumi += (feat_hid[j] * w_out[j][i]);
}
output[i] = round(accumi);
}
//Classify the output
if (output[0] == 1 && output[1] < 1 && output[2] < 1 && output[3] < 1)
{
classi = 1;
}
else if (output[0] < 1 && output[1] == 1 && output[2] < 1 && output[3] < 1)
{
classi = 2;
}
else if (output[0] < 1 && output[1] < 1 && output[2] == 1 && output[3] < 1)
{
classi = 3;
}
else if (output[0] < 1 && output[1] < 1 && output[2] < 1 && output[3] == 1)
{
classi = 4;
}
else
{
classi = 0;
}
Wire.beginTransmission(5);
Wire.write(classi);
//Wire.write(int(output[2]));
Wire.endTransmission();
Serial.println("wew");
Serial.println(output[0]);
Serial.println(output[1]);
Serial.println(output[2]);
Serial.println(output[3]);
//Serial.println(classi);
//Serial.println(feature[1]);
//Serial.println(feature[2]);
//Serial.println(feature[3]);
//Serial.println(feature[4]);
//Serial.println(feature[5]);
//Serial.println(feature[6]);
for (size_t i = 0; i < 10; i++)
{
feat_hid[i] = 0;
}
for (size_t i = 0; i < 4; i++)
{
output[i] = 0;
}
}while(analogRead(analogpin)>0);
}
But the real time implementation is rather dissatisfying, in which the output always mismatched, though by offline implementation is quite better.
My assumption is that the data capturing when online is rather bad, or maybe because any other things?
Thanks for any feedback
How did you train the network offline?
If you have used Matlab to train the network (i.e. to identify the weight and bias values) and then implement the same network on Arduino.
In such case we have problems with number precision. Matlab by default works on 64 bit precision whereas Arduino works on 32 bit.
Difference in the way the numbers are represented creates the Error.