Using C functions to select array values of index positions [3], [4] and [5] - c

I haven’t posted to a forum like this before, so I’ve tried to explain as clearly as possible, in as much detail as possible, to try to help anyone understand the problem I’m stuck on. I should add I’ve tried to dig for ages for a suitable function to help me in C but without resorting to parsing by looping on iterations of arrays, it seems no function(s) exist in C to get the job done more elegantly?
Anyway, I have a script which, when complete, will allow me to send specific integer value data, via a serial signal, to a dot matrix display.
I’m able to send the raw HEX data from an array/buffer to a dot matrix display using the script as it is. I also have the dot matrix script working well too so it displays the whole array of HEX data well. However, I want to refine the data by not only changing the data types in an array or buffer (named tempBuffer) from HEX to INT (or whatever is appropriate) but to also specifically select three items of data from their respective index positions in that eight item array/buffer (tempBuffer).
The problem looks like this:-
tempBuffer {0x4 0x41 0xC 0xB 0x90 0x0 0x0 0x0} // Raw hex data in array (buffer) - index positions 0 through 7.
I would like to select index positions [2], [3] and [4] in the above tempBuffer array and then place them consecutively into another array pending further processing (i.e. eventually adding item [3] and [4] together to produce one INT value representing a temperature, for example).
For example:
tempBuffer index item [2] would then be placed as Index item [0] in a new array, newArray . tempBuffer Items [3] & [4] would obviously become items [1] & [2] in newArray.
I plan to use newArray index item [0] as a condition check, for example, an if or case statement etc. The outcome of the clause would determine what happens next to the subsequent index items in [1] & [2]. It won’t always be necessary to use item [2] for data checking of a certain condition if item [0] is not met.
I could use a messy C loop/parsing iteration to extract the values I need from tempBuffer and place them in newArray. However, I wondered if there is a more elegant or existing function set existing in C which will allow me to get the job done more efficiently?
My query also applies I guess to possible function solutions in C to add the index values [1] and [2] together in newArray but if anyone can point me to a pre-existing function or an efficient means to iterate the arrays from above I should be grateful for any guidance, advice or pointers to further reading. Else, (excuse the pun) its back to using unwieldy looping and iteration in C statements to achieve the same outcome.

In the unlikely event anyone is following my original posting . . .
Thank you to those who tried to help.
Please excuse my syntax below, I'm 20 years out of practice with any coding. However, I don't care - it works!
I've managed to resolve my query and now have an adapted script (see section relating to my original stackoverflow query) running the way I want it to.
My adapted and integrated script now achieves the following:-
Read and *display (static, scroll, reverse & invert) Ford **ECU PID data (500Kb/11bit) relating to Vehicle Speed and RPM to a 10 x (8x8) LED Matrix display strip.
***Parse NEMA sentences to display on said matrix altitude and time-of-day data.
• I plan to change to Mikal Hart's TinyGPS++ libraries soon and adapt the script further to make it more efficient.
• I also plan to present a YouTube tutorial about my project.
*Thank you to Marco Colli (MajicDesigns) Parola libraries.
****Thank you to Seeed Studio's example script, OBDII_PIDs, as a base starting point.**
*** Thank you to "ludektalian" for further inspiration.
Thank you,
**# Define this_that_and_the_other;
String = "Only fraction of script";
blah - - -
blah - - -
blah . . .
unsigned char newArray[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
unsigned char serialOutArray[3] = {0,0,0};
if(CAN_MSGAVAIL == CAN.checkReceive()) // check data acquisition
{
CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf
for(int i = 0; i<len; i++) // print the data
{
newArray [i] = buf[i], HEX;
}
serialOutArray [0] = newArray [2]; // create 3 item array (new array)
serialOutArray [1] = newArray [3]; // from original 8 item array (buf) which
serialOutArray [2] = newArray [4]; // assign 'new array' to
delay(100); //'serialOutArray'
for (int y = 0; y<13; y++)
{
if (int(serialOutArray [0]) == 5) // Coolant in Celsius
{
delay(100);
colSub = int(serialOutArray[1]);
colTot = (colSub-40);
P.print(colTot + "C");
delay(500);
colSub = 0;
colTot = 0;
break;
}
if (int(serialOutArray [0]) == 12) // RPM
{
rpmA = int(serialOutArray [1])*256;
rpmB = int(serialOutArray [2]);
subRPM = (rpmA + rpmB);
rpmTot = subRPM/4;
P.print(rpmTot + "RPM");
break;
}
if (int(serialOutArray [0]) == 13) // MPH
{
mphA = serialOutArray[1];
mphTot = mphA*0.621371192;
P.print(mphTot + "MPH");
break;
}

Related

Printing number of items in a range from an array in Kotlin

Currently working on a little school assignment, trying to figure out if there is a specific way to print items out of a randomized array. Teacher wants us to generate 200 random numbers in a range of 1 through 100, store them, and then print them with the amount of each range(10s, 20s, 30s, etc). I've gotten the randomization and storage down, but I'm having a little issue trying to figure out how to properly display these.
We should have them separated by how many random numbers are 1-10, 11-20, etc etc, but also with a histograph to the side. I think I can figure out the histograph well enough, but I could use some help on how to display the numbers for each range! I hope this makes sense, any help is appreciated!
What I have so far is very simple, just having a rough time figuring out what goes in the println()
fun main() {
val rnds = (1..200).map { (1..100).random() }
println() // <-- ???
}
it should look something like:
1 - 10: # // <-- number of randomized numbers in that range here
11 - 20: # // <-- number of randomized numbers in that range here
21 - 30: # // <-- number of randomized numbers in that range here
etc etc, all the way until 91 - 100
I should also mention that I'm VERY new to kotlin, and still pretty green to programming in general. The easier the solution, the better, at least until I have a better understanding at what I'm seeing.
You can create your range buckets by using the map function on a range of each starting number of a bucket, and then associateWith to sort the original lists into these buckets:
val byRanges: Map<IntRange, List<Int>> = (1..100 step 10)
.map { it..(it + 9) }
.associateWith { range -> rnds.filter { it in range } }
Then when you want to convert this to text, you can use the joinToString() function on the map entries to format each item as text:
val asText: String = byRanges.entries.joinToString("\n") { (range, list) ->
"${range.start} - ${range.endInclusive}: # ${list.size}"
}
You can increase the "for" loop by range value and filter the list with desired condition to get the item count.
fun main() {
val randomRangeStart = 1
val randomRangeEnd = 100
val list = (1..200).map { (randomRangeStart..randomRangeEnd).random() }
for (i in randomRangeStart..randomRangeEnd step 10) {
println("Range $i - ${i+9}: ${list.filter { it >= i && it <= i+9 }.count()}")
}
}

How to make what function I use in c be controlled by a variable

This is my first year of vex. I am taking on the role of programmer.
I have had this idea for rapid autonomous creation, recording the driver. Instead of the usual array/debugger dump of raw streams of power levels, I had the idea of extracting functions from driver movement.
I wont go into the details, and I can code it myself, but I need some help.
There is one thing I am unable to do simply because of my lack of coding experience.
I want to create a for loop that checks every joystick button one by one.
For example:
struct button
{
bool pressed;
}
for(int i = 0; i>12; i++) //12 is number of buttons on the joystick
{
struct button button<cycle through buttons>;
}
I want there to then be:
struct button button6U;
struct button button6D;
struct button button6R;
etc.
Then, I want this:
for(int i = 0; i>12; i++) // 12 is number of buttons on the joystick
{
if(VexRT[<currentButton>])
{
button<currentButton>.pressed = true;
}
}
I have no idea how to do this, with a wildcard modifing the actual variable name I am writing to.
A couple thoughts:
A for statement would have no idea how to advance the order of joystick buttons. So something I think I might need is:
orderOfButtons
{
VexRT[6U];
VexRT[6D];
VexRT[6R];
// etc.
}
I just cant seem to figure out how to have a variable defining what VexRT[]button I am reading from.
Any help would be appreciated!
Thanks.
Sounds like you want an array:
#define NUMBER_OF_BUTTONS 12
...
struct button VexRT[NUMBER_OF_BUTTONS];
If you want to use symbolic constants to refer to specific buttons in the array, you can use an enumeration:
enum btn_id { BTN_6U, // maps to 0
BTN_6D, // maps to 1
BTN_6R, // maps to 2
...
}
Enumeration constants are represented as integers, and by default they start at 0 and increment by 1. You can initialize them to different values if you want, and multiple enumeration constants can map to the same value. I take advantage of this when I want to identify a "first" and "last" enumeration for looping, like so:
enum btn_id {
BTN_6U,
BTN_FIRST = BTN_6U, // both BTN_FIRST and BTN_6U will map to 0
BTN_6D,
BTN_6R,
...
BTN_whatever,
BTN_LAST
};
Thus, VexRT[BTN_6U] maps to VexRT[0], VexRT[BTN_6D] maps to VexRT[1], etc.
Note that this way, you don't have to loop through all the buttons just to set one:
enum btn_id currentButton = BTN_6D;
...
VexRT[currentButton].pressed = true;
If you do want to loop through the whole set, you can use
for ( enum btn_id i = BTN_FIRST; i < BTN_LAST; i++ )
{
VexRT[i].pressed = false;
}
So, what you want is to sample the user input (at some specified rate), then record it into an array, then play that back at a later time? If you have functions that drive the VEX (I'm not familiar with that), each of which are associated with an input, you can use an array of function pointers to create your output.
#define MAX_ACTION 12
#define MAX_RECORDED 200
// Declare your array of function pointers
int (*action[MAX_ACTION])(void);
// Declare your stored array of recorded actions
int recorded[MAX_RECORDED];
...
// Assign function pointers to associated functions
action[0] = go_forward;
action[1] = turn_right;
...
// Record your actions into some array
while (...)
{
// Record the action
recorded[i++] = get_action();
// Sample delay
}
...
// Playback the actions
for (i=0;i<RECORDED;i++)
{
(*action[recorded[i]])();
// delay here
}
P.S. Your for loop is backward (i<12 not i>12).
I think you are trying to access the events coming from the joystick. You can just loop through the array of values and record them. I think the channels on the joystick are simply accessed like: vexRT[x] where x is 1-12. If you just want to store the latest value from each channel you could do this:
int value[12];
for(i=0; i<12; i++)
{
value[i] = vexRT[i];
}
If you want to store all of the values so that you can map them or play them back or something then you will need a more complex data structure to store them, like a list of the value arrays.
I also have found documentation that says the values are accessed by like vexRT[Chx] where x is 1-12, so you could alternatively create a string and use it to access the joystick channels inside your loop:
string *s = (char *)malloc(5*sizeof(char)); //5 is the max length of the null terminated string
for() . . . {
sprintf(s,"Ch%d", i);
value[i] = vertRT[s];
}

Append function overwrites existing data in slice

I wrote a small application which records data from a sound card and stores the data in an array for later processing.
Whenever new data is available, portaudio executes the callback record. Within the callback I append the data to the array RecData.data.
The golang builtin function append adds as expected another element to the slice, but for whatever reason also overwrites all existing elements within the array with exactly the same data.
I have been trying to isolate the problem for more than two days, without success.
Here is a stripped down version of the code, which works and shows the problem:
package main
import (
"fmt"
"time"
// "reflect"
"github.com/gordonklaus/portaudio"
)
type RecData struct{
data [][][]float32
}
func main() {
var inputChs int = 1
var outputChs int = 0
var samplingRate float64 = 48000
var framesPerBuffer int = 3 //for test purpose that low. Would normally be 1024 or 2048
rec := RecData{make([][][]float32, 0, 1000)}
portaudio.Initialize()
stream, err := portaudio.OpenDefaultStream(inputChs, outputChs, samplingRate, framesPerBuffer, rec.record)
if err != nil {
fmt.Println(err)
}
defer stream.Close()
stream.Start()
for {
time.Sleep(time.Millisecond * 10)
}
}
// callback which gets called when new data is in the buffer
func (re *RecData)record(in [][]float32) {
fmt.Println("Received sound sample: ")
fmt.Println(in)
re.data = append(re.data, in)
fmt.Println("Content of RecData.data after adding received sound sample:")
fmt.Println(re.data, "\n")
time.Sleep(time.Millisecond * 500) //limit temporarily the amount of data read
// iterate over all recorded data and compare them
/*
for i, d := range re.data{
if reflect.DeepEqual(d, in){
fmt.Printf("Data at index %d is the same as the recorded one, but should not be!\n", i )
}
}*/
}
2. Update
This is the application output:
Received sound sample:
[[0.71575254 1.0734825 0.7444282]]
Content of RecData.data after adding received sound sample:
[[[0.71575254 1.0734825 0.7444282]]]
Received sound sample:
[[0.7555193 0.768355 0.6575008]]
Content of RecData.data after adding received sound sample:
[[[0.7555193 0.768355 0.6575008]] [[0.7555193 0.768355 0.6575008]]]
Received sound sample:
[[0.7247052 0.68471473 0.6843796]]
Content of RecData.data after adding received sound sample:
[[[0.7247052 0.68471473 0.6843796]] [[0.7247052 0.68471473 0.6843796]] [[0.7247052 0.68471473 0.6843796]]]
Received sound sample:
[[0.6996536 0.66283375 0.67252487]]
Content of RecData.data after adding received sound sample:
[[[0.6996536 0.66283375 0.67252487]] [[0.6996536 0.66283375 0.67252487]] [[0.6996536 0.66283375 0.67252487]] [[0.6996536 0.66283375 0.67252487]]]
.... etc ....
As we one can see, over time, the size of the slice is growing, but instead of just appending the data, the data in the array gets also overwritten.
This should not happen. portaudio provides in the callback a [][]float32 with the audio sample recorded from the sound card. As you can see they are always different.
As mentioned, the code above is a stripped down version of my application. Usually I would record lets say 5 seconds, and then perform a Fast Fourier Transformation (FFT) over the samples to calculate the spectrum. I left this part away since it has no impact on this particular problem.
I would very much appreciate any help. Maybe somebody can point me out what I'm doing wrong.
Thanks!
The buffer passed into the callback is reused by the portaudio package, so you are appending the same slice structure to your data slice. Each time the buffer allocated by portaudio overwrites the data, you see the results in every element of your data slice.
You will need to allocate new slices and make a copy of the data:
func (re *RecData) record(in [][]float32) {
buf := make([][]float32, len(in))
for i, v := range in {
buf[i] = append([]float32(nil), v...)
}
re.data = append(re.data, buf)
Example:
https://play.golang.org/p/cF57lQIZFU

Array of structures in MATLAB Simulink

I am trying to create an array of structures in Simulink and got some problems with it.
first of all i tried to create it directly in Simulink using this:
function a = fcn(Dibhole, t , x, const)
%#codegen
%Output = zeros(10,10);
f1 = 'number';
f2 = 'move';
cube = struct(f1, 0, f2, 0);
a = repmat(cube, 20, 10);
for i = 1:20
for j = 1:10
a(i,j).number = 0;
a(i,j).move = 0;
end
end
and i got this error:
Derived output was of type struct. 'Inherited type' is unsupported for this
type and a defined bus object must be used instead. Click on 'a' and
set data type for 'a' to be 'Bus: ', where '' is
the name of a bus object from the MATLAB workspace.
So i found some example how to create struct in Matlab and receive this to Simulink: http://blogs.mathworks.com/seth/2011/12/05/initializing-buses-using-a-matlab-structure/
That works perfectly but i still can't repeat this with array:
f1 = 'number';
f2 = 'move';
cube = struct(f1, 0, f2, 0);
myStruct2 = repmat(cube, 20, 10);
for i = 1:20
for j = 1:10
myStruct2(i,j).number = 1;
myStruct2(i,j).move = 1;
end
end
busInfo = Simulink.Bus.createObject(myStruct2);
Can anyone clarify to me what's the problem? Or maybe there is different way to create array of struct in Simulink?
Mihail
Simulink wants you to define the output of the function to be a bus.
As 'Bus: My_test_bus', for example.
Take a look at the Simulink Bus Editor. You can find it in any model under the menu, Edit->Bus Editor.
This would be a good start.
Rick, i think you are right!
i have tried this problem for a long time, and have got this results:
the irony is that I was never able to create array of structures BUT i did this with structure of arrays! :D
I made this steps for it:
to use structure of arrays we need to define and initialize it in some MATLAB function. Like this:
number = zeros(10,1);
move = zeros(10,1);
for i = 1:10
number(i,1) = i+1;
move(i,1) = i+2;
end
a = struct('numbers',number,'movement', move);
To work this data we must use Bus Selector.
So we have array in "numbers" and "movement".
BUT! Here we go, Rick: we must define type of output of MATLAB function like Bus! How to do this in simulink? i found this way:
in model properties in simulink Callbacks/PreLoadFcn define some function and in same folder as project create .m file named like this just defined function.
In this file create structure of array and define Bus type for it:
number = zeros(10,1);
move = zeros(10,1);
a = struct('numbers',number,'movement', move);
busInfo = Simulink.Bus.createObject(a);
Now we have Bus type for our structure at first loading of simulink model.
Last step: define MATLAB function output type directly.
in Model Explorer choose your MATLAB function. choose output variable. Set DataType for it: Bus:slBus1 (the name of this Bus type you can see in wokspace of matlab, because its a global variable).
That's all! now it works!
(tried to add pictures, but i have no enough reputation :( )
Now my program works in this way, but i also tried to create array of structures and still have the problems. i tried to create Bus for it, but can't transmit it to Bus Selector - it doesn't know what to do with structures... i also tried to add one more MATLAB function to create some data from structures and then display it, but it doesn't works too(

How to change the elements of an array in perl when the order of the array changes depending on where the program is run?

EDIT: Figured it out using a subroutine and a whole lot of if statements. I've appended the working code to the bottom of the question (since it won't let me post an answer) in case someone comes across a similar issue, with the disclaimer that I'm a mega-novice and the code probably isn't good, just functional.
Thanks for the help, guys!
Original Question:
I'm currently banging my head against an assignment that requires we use the Win32::DriveInfo module to create a list of drives, followed by the drive type. Using an array, we have to take the supplied drive type number and convert it into a descriptive string.
I can get the program to return the appropriate drive type, the problem is converting those numbers into strings. The array is populated based on the drives it finds on the user's system, which means the program has to be able read the array, determine each number, and then (probably?) compare it against some kind of predetermined 'conversion chart' and convert the provided numbers to the appropriate string.
I've been at this for hours, and so far my best option seems like it might be the map function, although we haven't gone over that in class (and my teacher is not fond of googling) so I'm not entirely sure that's what we're supposed to use. And even so, the only information I've been able to find has either been completely over my head, or assumes that the contents of the array are static.
The entire program is longer, but here's the relevant code:
use Win32::DriveInfo;
my #DrivesInUse = Win32::DriveInfo::DrivesInUse();
my #DriveType;
my %DrivesHash;
foreach $DrivesInUse (#DrivesInUse)
{
print "$DrivesInUse: ";
push (#DriveType, Win32::DriveInfo::DriveType($DrivesInUse));
foreach $DriveType (#DriveType)
{
$DrivesHash{$DrivesInUse} = $DriveType;
}
print $DrivesHash{$DrivesInUse} . "\n";
}
And the output is:
A: 2
C: 3
D: 5
E: 5
F: 5
G: 2
Now I just have to figure out a way to convert all potential numbers (0-6) to the appropriate strings and print those instead. We can't use any additional modules, and considering I'm still very much a newbie, the more basic the solution the better.
Edit:
For clarification, the numbers come from the Win32::DriveInfo module, and each of them represent a drive type, description from CPAN below:
0 - the drive type cannot be determined.
1 - the root directory does not exist.
2 - the drive can be removed from the drive (removable).
3 - the disk cannot be removed from the drive (fixed).
4 - the drive is a remote (network) drive.
5 - the drive is a CD-ROM drive.
6 - the drive is a RAM disk.
In my program, I need those numbers to return as descriptive strings instead, so the desired output on my system would be something like:
A: Removable Drive
C: Fixed Drive
D: CD-ROM Drive
E: CD-ROM Drive
F: CD-ROM Drive
G: Removable Drive
My problem is I can't figure out how to convert the numbers in #DriveType to the corresponding strings, since the elements in #DriveType change depending on the system.
I hope that cleared things up?
Working Code
use Win32::SystemInfo;
use Win32::DriveInfo;
my #DrivesInUse = Win32::DriveInfo::DrivesInUse();
my #DriveType;
my %DrivesHash;
foreach $DrivesInUse (#DrivesInUse)
{
print "$DrivesInUse: ";
push (#DriveType, Win32::DriveInfo::DriveType($DrivesInUse));
foreach $DriveType (#DriveType)
{
$DriveString = conversion($DriveType);
$DrivesHash{$DrivesInUse} = $DriveString;
}
print $DrivesHash{$DrivesInUse} . "\n";
}
sub conversion
{
if ($_[0] == 0)
{
$StringContent = "Undetermined";
}
if ($_[0] == 1)
{
$StringContent = "Does not exist";
}
if ($_[0] == 2)
{
$StringContent = "Removable";
}
if ($_[0] == 3)
{
$StringContent = "Fixed";
}
if ($_[0] == 4)
{
$StringContent = "Network";
}
if ($_[0] == 5)
{
$StringContent = "CD-ROM";
}
if ($_[0] == 6)
{
$StringContent = "RAM";
}
return $StringContent;
}
I hope this may help you
use Win32::DriveInfo;
my #DrivesInUse = Win32::DriveInfo::DrivesInUse();
my %DriveType = (
'0' => 'Undetermined',
'1' => 'Does not exist',
'2' => 'Removable',
'3' => 'Fixed',
'4' => 'Network',
'5' => 'CD-ROM',
'6' => 'RAM',
);
for $DrivesInUse ( #DrivesInUse ) {
print "$DrivesInUse: "
. $DriveType{ Win32::DriveInfo::DriveType($DrivesInUse) } . "\n";
}
One way to go could be a types hash like
my %typesHash;
$typesHash{0} = "the drive type cannot be determined.";
$typesHash{1} = "the root directory does not exist.";
.
.
.
edit: In an earlier version i had butchered these lines. Another way to assign the hash would be the following, i just tried to use the version above because i thought it would be clearer and consequently managed to make everything less clear. \o/
my %typesHash = (0 => "the drive type cannot be determined.",
1 => "the root directory does not exist.",
...);
end edit
And later use
print $typesHash{$DrivesHash{$DrivesInUse}} . "\n";
Not necessarily the most elegant solution but a proper use for a hash.
edit:
By the way:
push (#DriveType, Win32::DriveInfo::DriveType($DrivesInUse));
foreach $DriveType (#DriveType)
{
$DrivesHash{$DrivesInUse} = $DriveType;
}
is a completely useless loop. It just assigns all the drive types encountered so far to $DrivesHash{$DrivesInUse} one after the other. It does work because you pushed the most recent one into the array last and so it will end up with the correct one but there is no reason to assign all the others before. If you do not need the array of drive types (they are in the hash as well anyways), the whole stuff pasted above could be replaced with:
$DrivesHash{$DrivesInUse} = Win32::DriveInfo::DriveType($DrivesInUse);

Resources